Added auto-evaluation.

This commit is contained in:
2021-06-23 18:17:07 +02:00
parent 85b67f45e6
commit e534c0d5f9
3 changed files with 132 additions and 29 deletions
+3
View File
@@ -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>
+110 -18
View File
@@ -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 = [];
+13 -5
View File
@@ -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 {