From 6681f0ec1cce3c692b918d95f3cfd81acc14ae72 Mon Sep 17 00:00:00 2001
From: Adam Piontek <adam@73k.us>
Date: Sun, 11 Sep 2022 09:05:00 -0400
Subject: [PATCH] improved input to allow any delimeter, or no delimeter, still
 allowing '0' for unknown cards

---
 index.html | 37 ++++++++++++++-----------------------
 main.js    | 27 +++++++++++++++------------
 2 files changed, 29 insertions(+), 35 deletions(-)

diff --git a/index.html b/index.html
index 3280efd..e946b48 100644
--- a/index.html
+++ b/index.html
@@ -13,7 +13,17 @@
         <div class="col pt-3 pt-lg-5">
           <h1>Tripeaks Solver</h1>
 
-          <p x-data="helloilove" x-text="message"></p>
+          <p>Enter cards representing a Tripeaks game below. Enter each card as 2 characters each, representing the rank (A, 2, 3, 4, 5, 6, 7, 8, 9, T, J, Q, K) and suit (C, D, H, S). For example, "TH" is the Ten of Hearts.</p>
+
+          <p>Use a 0 (zero) to represent unknown cards. However, all cards from the last row and the stock must be known (i.e., you must enter valid cards for the last 34 cards)</p>
+
+          <p>Entry is case-insensitive, and you may use either any delimeter (space, comma, colon, etc.) or no delimeter. Valid examples:</p>
+
+          <ul>
+            <li>0 TS 0 7S 5D 7C 2D 0 0 3S 2H 3H 9H KC QC TD 8D 9C 7H 9D JS QS 4H 5C 5S 4C 2C QD 8C KD 3D KS JD 2S 7D KH AH 5H 9S 4S QH 6S 6D 3C JC TC 8H 6C TH AS AD 6H</li>
+            <li>jc,ts,6d,7h,qh,3s,5h,jh,6h,2d,ac,7s,7c,3d,kd,9s,3c,th,6c,ah,8h,tc,4s,8c,ad,3h,ks,6s,js,7d,jd,td,2c,kh</li>
+            <li>7c03s0qsjc00JSasTSadtcqd9s4s2h9h8sjh6c3dks5s5c6h9C2Cac8C6d5DTH8dkckd9d4c5h8hqh6s</li>
+          </ul>
 
           <form
             id="cardsInputForm"
@@ -34,9 +44,9 @@
                 x-model="inputValue"
                 class="form-control"
                 :class="{ 'is-valid': isFormValid && inputValue.length > 2, 'is-invalid': !isFormValid && inputValue.length > 2 }"
-                maxlength="155"
-                @keyup.debounce="validateCardsInput($event)"
-                placeholder="e.g., 2S TC 4S QD KH 5S 9S ..."
+                maxlength="206"
+                @keyup.debounce="validateCardsInput()"
+                :placeholder="useDelim ? 'e.g., 2S TC 4S QD KH 5S 9S ...' : 'e.g., 2STC4SQDKH5S9S...'"
               />
 
               <template x-for="msg in validMessages">
@@ -74,25 +84,6 @@
             </div>
           </form>
 
-          <!-- <div x-data="cardInput">
-
-            <div class="mb-3">
-
-              <label for="userCardEntryInput" class="form-label" id="userCardEntryInputHelp">Enter Game Cards</label>
-              <input @keyup.debounce="validateCardString($event)" class="form-control" :class="{ 'is-valid': inputIsValid, 'is-invalid': !inputIsValid }" id="userCardEntryInput" aria-describedby="userCardEntryInputHelp" maxlength="155" placeholder="e.g., 2S TC 4S QD KH 5S 9S ...">
-
-              <div class="valid-feedback" :class="{ 'd-block': validUserCards.filter(c => c !== '0').length > 0 }" x-text="validatedCardsStr(validUserCards.filter(c => c != '0'), 'valid')"></div>
-
-              <div class="valid-feedback text-muted" :class="{ 'd-block': validUserCards.filter(c => c === '0').length > 0 }" x-text="`${52 - validUserCards.filter(c => c !== '0').length} unknown card${validUserCards.filter(c => c === '0').length > 1 ? 's' : ''}`"></div>
-
-              <div class="invalid-feedback" :class="{ 'd-block': dupedUserCards.length > 0 }" x-text="validatedCardsStr(dupedUserCards, 'duplicate')"></div>
-
-              <div class="invalid-feedback" :class="{ 'd-block': invalidUserCards.length > 0 }" x-text="validatedCardsStr(invalidUserCards, 'invalid')"></div>
-
-              <div class="invalid-feedback" :class="{ 'd-block': invalidLength !== '' }" x-text="invalidLength"></div>
-            </div>
-
-          </div> -->
         </div>
       </div>
     </div>
diff --git a/main.js b/main.js
index 8076977..92ba599 100644
--- a/main.js
+++ b/main.js
@@ -2,12 +2,9 @@ import "./style.scss";
 import Alpine from "alpinejs";
 // import 'bootstrap/dist/js/bootstrap'
 
-Alpine.data("helloilove", () => ({
-  message: "I ❤️ Alpine",
-}));
-
 Alpine.data("cardsInputForm", () => ({
   // "constants" for validation etc
+  nonAlphaNumRegEx: /[\W_]+/g,
   suits: [],
   ranks: [],
   deck: [],
@@ -46,17 +43,26 @@ Alpine.data("cardsInputForm", () => ({
   get isValidCardsLengthInRange() {
     return !this.isValidCardsLengthTooSmall && !this.isValidCardsLengthTooBig;
   },
-  validateCardsInput(event) {
+  validateCardsInput() {
     // reset arrays and parse the input
     this.validCards = [];
     this.invalidCards = [];
     this.dupedCards = [];
     this.validMessages = [];
     this.invalidMessages = [];
-    let userCards = event.target.value
-      .toUpperCase()
-      .split(" ")
-      .filter((c) => c);
+    // 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) => {
@@ -112,9 +118,6 @@ Alpine.data("cardsInputForm", () => ({
         `${this.validCards.length} valid card${s}: ${this.validCards.join(" ")}`
       );
     }
-    if (event.target.value.includes("  ")) {
-      this.invalidMessages.push("Too many spaces between cards");
-    }
 
     // set the game cards to try solving, based on current input
     this.cardsToSolve = Array(this.deck.length - this.validCards.length)