Added auto-evaluation.
This commit is contained in:
@@ -25,7 +25,10 @@
|
|||||||
</card-container>
|
</card-container>
|
||||||
</main-panel>
|
</main-panel>
|
||||||
<main-panel>
|
<main-panel>
|
||||||
|
Points: <span id="points">?</span>
|
||||||
|
<br>
|
||||||
<button onclick="reset();">Reset</button>
|
<button onclick="reset();">Reset</button>
|
||||||
|
<button onclick="cashOut();">Cash out</button>
|
||||||
<input type="checkbox" onclick="toggleAutoDraw(this)" id="autoDrawToggle" /><label for="autoDrawToggle">Auto-Draw</label>
|
<input type="checkbox" onclick="toggleAutoDraw(this)" id="autoDrawToggle" /><label for="autoDrawToggle">Auto-Draw</label>
|
||||||
<br>
|
<br>
|
||||||
<div style="margin-top: 1.4em;" id="result">?</div>
|
<div style="margin-top: 1.4em;" id="result">?</div>
|
||||||
|
|||||||
@@ -8,15 +8,19 @@ var sameColorExtra = 4; // extra points given for sets of the same color if they
|
|||||||
|
|
||||||
var autoDraw = false; // whether the script should automatically draw on start and on discard
|
var autoDraw = false; // whether the script should automatically draw on start and on discard
|
||||||
var autoRecommend = true; // whether the script should automatically recommend on change
|
var autoRecommend = true; // whether the script should automatically recommend on change
|
||||||
|
var measurePerformance = false; // whether the performance should be logged into the console
|
||||||
|
|
||||||
var allCards = undefined;
|
var allCards = undefined;
|
||||||
var deck = undefined;
|
var deck = undefined;
|
||||||
var hand = undefined;
|
var hand = undefined;
|
||||||
|
var globalPoints = undefined;
|
||||||
var recommendations = undefined;
|
var recommendations = undefined;
|
||||||
|
var minimumRecommendations = 1;
|
||||||
|
|
||||||
var deckElement = document.getElementById('deck');
|
var deckElement = document.getElementById('deck');
|
||||||
var handElement = document.getElementById('hand');
|
var handElement = document.getElementById('hand');
|
||||||
var recommendElement = document.getElementById('result');
|
var recommendElement = document.getElementById('result');
|
||||||
|
var pointsElement = document.getElementById('points');
|
||||||
|
|
||||||
reset();
|
reset();
|
||||||
|
|
||||||
@@ -62,9 +66,11 @@ function cardToElement(card, forDeck = false, drawn = false) {
|
|||||||
|
|
||||||
if (!forDeck) {
|
if (!forDeck) {
|
||||||
if (recommendations.length > 0 ) {
|
if (recommendations.length > 0 ) {
|
||||||
if (recommendations[0].burnedCard && recommendations[0].burnedCard == card.id) {
|
if (recommendations[0].burnedCard) {
|
||||||
|
if (recommendations[0].burnedCard == card.id) {
|
||||||
element.classList.add("discard");
|
element.classList.add("discard");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else if (recommendations[0].cards && recommendations[0].cards.includes(card.id)) {
|
else if (recommendations[0].cards && recommendations[0].cards.includes(card.id)) {
|
||||||
element.classList.add("select");
|
element.classList.add("select");
|
||||||
}
|
}
|
||||||
@@ -112,7 +118,7 @@ function fillHand() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function discard(cardId, thisHand = null) {
|
function discard(cardId, thisHand = null, update = true) {
|
||||||
let handGiven = true;
|
let handGiven = true;
|
||||||
if (thisHand == null) {
|
if (thisHand == null) {
|
||||||
thisHand = hand;
|
thisHand = hand;
|
||||||
@@ -127,10 +133,51 @@ function discard(cardId, thisHand = null) {
|
|||||||
fillHand();
|
fillHand();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!handGiven && update) {
|
||||||
|
updateUI();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function cashOut(thisHand = null) {
|
||||||
|
if (recommendations.length > 0) {
|
||||||
|
let handGiven = true;
|
||||||
|
if (thisHand == null) {
|
||||||
|
thisHand = hand;
|
||||||
|
handGiven = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("Recommendation: ");
|
||||||
|
console.log(recommendations[0]);
|
||||||
|
|
||||||
|
if (recommendations[0].burnedCard) {
|
||||||
|
console.log("Discarding: " + recommendations[0].burnedCard);
|
||||||
|
discard(recommendations[0].burnedCard, thisHand, false);
|
||||||
|
}
|
||||||
|
else if (recommendations[0].pattern && recommendations[0].cards) {
|
||||||
|
let localPoints = recommendations[0].points;
|
||||||
|
|
||||||
|
let localCards = [...recommendations[0].cards];
|
||||||
|
|
||||||
|
// reset recommendations
|
||||||
|
recommendations = [];
|
||||||
|
|
||||||
|
for (let cardId of localCards) {
|
||||||
|
console.log("Redeeming: " + cardId);
|
||||||
|
discard(cardId, thisHand, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
globalPoints += localPoints;
|
||||||
|
console.log("Cashed out: " + (localPoints * pointsMultiplier) + " points");
|
||||||
|
}
|
||||||
|
|
||||||
if (!handGiven) {
|
if (!handGiven) {
|
||||||
updateUI();
|
updateUI();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
console.log("Nothing to cash out.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function drawCard(cardId, thisHand = null, thisDeck = null) {
|
function drawCard(cardId, thisHand = null, thisDeck = null) {
|
||||||
let handGiven = true;
|
let handGiven = true;
|
||||||
@@ -156,8 +203,7 @@ function drawCard(cardId, thisHand = null, thisDeck = null) {
|
|||||||
|
|
||||||
function recommend() {
|
function recommend() {
|
||||||
var cardCount = Object.keys(allCards).length
|
var cardCount = Object.keys(allCards).length
|
||||||
var scale = 6;
|
recommendOfDepth(6);
|
||||||
recommendOfDepth(scale);
|
|
||||||
updateUI(true);
|
updateUI(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -194,7 +240,6 @@ function getPatterns(thisHand = null) {
|
|||||||
|
|
||||||
let cardIds = [];
|
let cardIds = [];
|
||||||
for (let card of cardsByNumbers[i]) {
|
for (let card of cardsByNumbers[i]) {
|
||||||
console.log(card);
|
|
||||||
cardIds.push(cardToId(card));
|
cardIds.push(cardToId(card));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,6 +267,11 @@ function getPatterns(thisHand = null) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isSeries) {
|
if (isSeries) {
|
||||||
|
let sameColor = false;
|
||||||
|
if (theseColors.length > 0) {
|
||||||
|
sameColor = true;
|
||||||
|
}
|
||||||
|
|
||||||
let patternName = (i + 1).toString();
|
let patternName = (i + 1).toString();
|
||||||
for (let numberOffset = 1; numberOffset < seriesLength; numberOffset++) {
|
for (let numberOffset = 1; numberOffset < seriesLength; numberOffset++) {
|
||||||
patternName += "-" + (i + numberOffset + 1).toString();
|
patternName += "-" + (i + numberOffset + 1).toString();
|
||||||
@@ -230,16 +280,30 @@ function getPatterns(thisHand = null) {
|
|||||||
// "i" is lagging behind, adjustment needed
|
// "i" is lagging behind, adjustment needed
|
||||||
let points = (i + 1);
|
let points = (i + 1);
|
||||||
|
|
||||||
// check if they are of the same color
|
if (sameColor) {
|
||||||
if (theseColors.length > 0) {
|
|
||||||
points = ((i + 1) + sameColorExtra);
|
points = ((i + 1) + sameColorExtra);
|
||||||
patternName += "*";
|
patternName += "*";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// try to regather the cards
|
||||||
|
let allowedColors = theseColors;
|
||||||
|
let gatheredCards = [];
|
||||||
|
if (allowedColors.length < 1) {
|
||||||
|
allowedColors = colors;
|
||||||
|
}
|
||||||
|
for (let numberOffset = 0; numberOffset < seriesLength; numberOffset++) {
|
||||||
|
for (let card of cardsByNumbers[i + numberOffset]) {
|
||||||
|
if (allowedColors.includes(card.color)) {
|
||||||
|
gatheredCards.push(card.id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
patterns[patternName] = {};
|
patterns[patternName] = {};
|
||||||
patterns[patternName].pattern = patternName;
|
patterns[patternName].pattern = patternName;
|
||||||
patterns[patternName].points = points;
|
patterns[patternName].points = points;
|
||||||
patterns[patternName].cards = [];
|
patterns[patternName].cards = gatheredCards;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,15 +324,16 @@ function getHandPoints(hand = null) {
|
|||||||
return { pattern: "none", points: 0 };
|
return { pattern: "none", points: 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
function recommendOfDepth(depth = 2) {
|
function recommendOfDepth(depth = 0) {
|
||||||
|
if (measurePerformance) {
|
||||||
var t0 = performance.now();
|
var t0 = performance.now();
|
||||||
|
}
|
||||||
|
|
||||||
recommendations = [];
|
recommendations = [];
|
||||||
recommendThrowaway(depth);
|
recommendThrowaway(depth);
|
||||||
let current = getHandPoints();
|
let current = getHandPoints();
|
||||||
if (current.points > 0) {
|
if (current.points > 0) {
|
||||||
let choice = {
|
let choice = {
|
||||||
burnedCard: "CASH OUT",
|
|
||||||
points: current,
|
points: current,
|
||||||
chance: 1,
|
chance: 1,
|
||||||
points: current.points,
|
points: current.points,
|
||||||
@@ -278,9 +343,11 @@ function recommendOfDepth(depth = 2) {
|
|||||||
recommendations.unshift(choice);
|
recommendations.unshift(choice);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (measurePerformance) {
|
||||||
var t1 = performance.now();
|
var t1 = performance.now();
|
||||||
console.log("Took " + (t1 - t0) + " milliseconds.");
|
console.log("Took " + (t1 - t0) + " milliseconds.");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function recommendThrowaway(depth = 0, thisHand = null, thisDeck = null, chance = 1, firstDiscarded = null) {
|
function recommendThrowaway(depth = 0, thisHand = null, thisDeck = null, chance = 1, firstDiscarded = null) {
|
||||||
if (thisHand == null) {
|
if (thisHand == null) {
|
||||||
@@ -336,15 +403,32 @@ function recommendThrowaway(depth = 0, thisHand = null, thisDeck = null, chance
|
|||||||
|
|
||||||
choice.chance = thisChance
|
choice.chance = thisChance
|
||||||
recommendations.push(choice);
|
recommendations.push(choice);
|
||||||
|
|
||||||
if (depth > 0 && recommendations.length < 1) {
|
|
||||||
recommendThrowaway(depth - 1, hands[choice.index], decks[choice.index], thisChance, choice.burnedCard);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// compress recommendations
|
||||||
|
if (choices.length > 0) {
|
||||||
|
recommendations = [...new Set(recommendations)];
|
||||||
|
|
||||||
|
// only allow one recommendation per pattern
|
||||||
|
let newRecs = [];
|
||||||
|
for (let rec of recommendations) {
|
||||||
|
if (!newRecs.map(newRec => newRec.pattern).includes(rec.pattern)) {
|
||||||
|
newRecs.push(rec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
recommendations = newRecs;
|
||||||
|
}
|
||||||
|
|
||||||
|
// recursive
|
||||||
|
for (let choice of choices) {
|
||||||
|
if (depth > 0 && recommendations.length < minimumRecommendations) {
|
||||||
|
recommendThrowaway(depth - 1, hands[choice.index], decks[choice.index], choice.chance, choice.burnedCard);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (firstDiscarded == null) {
|
if (firstDiscarded == null) {
|
||||||
recommendations = [...new Set(recommendations)];
|
|
||||||
recommendations.sort((a, b) => {
|
recommendations.sort((a, b) => {
|
||||||
var place = 0
|
var place = 0
|
||||||
if (a.chance > b.chance) {
|
if (a.chance > b.chance) {
|
||||||
@@ -361,10 +445,10 @@ function recommendThrowaway(depth = 0, thisHand = null, thisDeck = null, chance
|
|||||||
}
|
}
|
||||||
return place;
|
return place;
|
||||||
});
|
});
|
||||||
let fewer = recommendations.filter(choice => choice.chance >= 0.01);
|
// let fewer = recommendations.filter(choice => choice.chance >= 0.01);
|
||||||
if (fewer.length > 0) {
|
// if (fewer.length > 0) {
|
||||||
recommendations = fewer;
|
// recommendations = fewer;
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -385,8 +469,13 @@ function getRecommendationText(rec) {
|
|||||||
|
|
||||||
function updateUI(skipAuto = false) {
|
function updateUI(skipAuto = false) {
|
||||||
if (autoRecommend && !skipAuto) {
|
if (autoRecommend && !skipAuto) {
|
||||||
|
if (hand.length >= handSize) {
|
||||||
recommend();
|
recommend();
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
// recommendations = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
recommendationArray = [];
|
recommendationArray = [];
|
||||||
for (let recommendation of recommendations) {
|
for (let recommendation of recommendations) {
|
||||||
recommendationArray.push(getRecommendationText(recommendation));
|
recommendationArray.push(getRecommendationText(recommendation));
|
||||||
@@ -411,9 +500,12 @@ function updateUI(skipAuto = false) {
|
|||||||
deckElement.innerHTML += cardToElement(card, true, true);
|
deckElement.innerHTML += cardToElement(card, true, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pointsElement.innerHTML = Math.floor(globalPoints * pointsMultiplier);
|
||||||
}
|
}
|
||||||
|
|
||||||
function reset() {
|
function reset() {
|
||||||
|
globalPoints = 0;
|
||||||
allCards = {};
|
allCards = {};
|
||||||
deck = [];
|
deck = [];
|
||||||
hand = [];
|
hand = [];
|
||||||
|
|||||||
@@ -29,11 +29,16 @@
|
|||||||
--yellow-card-background: #c49000;
|
--yellow-card-background: #c49000;
|
||||||
|
|
||||||
--card-inset-shadow: #000000;
|
--card-inset-shadow: #000000;
|
||||||
--card-border-color: #ffffff;
|
--card-inset-shadow-variant: #ffffff;
|
||||||
|
--card-border: #ffffff;
|
||||||
|
--card-border-variant: #000000;
|
||||||
|
|
||||||
--card-height: 70px;
|
--card-height: 70px;
|
||||||
--card-width: 55px;
|
--card-width: 55px;
|
||||||
--card-font-size: 30pt;
|
--card-font-size: 30pt;
|
||||||
|
|
||||||
|
--discard: red;
|
||||||
|
--cash-out: green;
|
||||||
}
|
}
|
||||||
|
|
||||||
* {
|
* {
|
||||||
@@ -100,8 +105,11 @@ panel-title {
|
|||||||
color: var(--text-disabled);
|
color: var(--text-disabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
.discard, .select {
|
.discard {
|
||||||
box-shadow: inset 0 0 50px -10px white, 0 0 10px -6px red;
|
box-shadow: inset 0 0 50px -10px var(--card-inset-shadow-variant), 0 0 6px 2px var(--discard), inset 0 0 10px -4px var(--discard);
|
||||||
|
}
|
||||||
|
.select {
|
||||||
|
box-shadow: inset 0 0 50px -10px var(--card-inset-shadow-variant), 0 0 6px 2px var(--cash-out), inset 0 0 10px -4px var(--cash-out);
|
||||||
}
|
}
|
||||||
|
|
||||||
card-container {
|
card-container {
|
||||||
@@ -139,11 +147,11 @@ okey-card:hover, okey-card:active {
|
|||||||
}
|
}
|
||||||
|
|
||||||
okey-card[clickable]:not([hand-full]):hover {
|
okey-card[clickable]:not([hand-full]):hover {
|
||||||
box-shadow: inset 0 0 50px -10px var(--card-inset-shadow), 0 0 3px 0 var(--card-border-color);
|
box-shadow: inset 0 0 50px -10px var(--card-inset-shadow), 0 0 3px 0 var(--card-border);
|
||||||
}
|
}
|
||||||
|
|
||||||
okey-card[clickable]:not([hand-full]):active {
|
okey-card[clickable]:not([hand-full]):active {
|
||||||
box-shadow: inset 0 0 50px -10px var(--card-inset-shadow), 0 0 3px 0 var(--card-border-color), inset 0 0 0 100px var(--primary);
|
box-shadow: inset 0 0 50px -10px var(--card-inset-shadow), 0 0 3px 0 var(--card-border), inset 0 0 0 100px var(--primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
okey-card:not([clickable]):active, okey-card[hand-full]:active {
|
okey-card:not([clickable]):active, okey-card[hand-full]:active {
|
||||||
|
|||||||
Reference in New Issue
Block a user