Created
May 23, 2020 08:11
-
-
Save zdraganov/bb809a3a4a93c7e71e7071ba772733fa to your computer and use it in GitHub Desktop.
DDS example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { dealerCompute } from 'results/utils/hands' | |
import { shortDirections } from 'results/constants' | |
const suitsSorted = ['S', 'H', 'D', 'C'] | |
const ranksSorted = ['A', 'K', 'Q', 'J', 'T', '9', '8', '7', '6', '5', '4', '3', '2'] | |
const pbnDirectionCardsOrder = { | |
N: ['N', 'E', 'S', 'W'], | |
E: ['E', 'S', 'W', 'N'], | |
S: ['S', 'W', 'N', 'E'], | |
W: ['W', 'N', 'E', 'S'] | |
} | |
function buildCard (cardString) { | |
const [rank, suit] = cardString.split('') | |
return { rank, suit } | |
} | |
function buildPbnCards (cards) { | |
const { S, H, D, C } = | |
cards.reduce((memo, card) => { memo[card.suit].push(card.rank); return memo }, | |
{ S: [], H: [], D: [], C: [] }) | |
return [S.join(''), H.join(''), D.join(''), C.join('')].join('.') | |
} | |
function sortPbnCards (cards) { | |
return cards.sort((c1, c2) => { | |
const suitCompared = suitsSorted.indexOf(c1.suit) - suitsSorted.indexOf(c2.suit) | |
if (suitCompared !== 0) { | |
return suitCompared | |
} | |
return ranksSorted.indexOf(c1.rank) - ranksSorted.indexOf(c2.rank) | |
}) | |
} | |
// The format is | |
function buildPbn ({ boardNumber, cardHolding }) { | |
const dealer = dealerCompute(boardNumber) | |
const sortOrder = pbnDirectionCardsOrder[shortDirections[dealer]] | |
const handString = Object.entries(cardHolding) | |
.sort(([directionA, _cardsA], [directionB, _cardsB]) => { | |
return sortOrder.indexOf(directionA) - sortOrder.indexOf(directionB) | |
}) | |
.map(([_, cards]) => { | |
return buildPbnCards( | |
sortPbnCards(cards.map(buildCard)) | |
) | |
}) | |
.join(' ') | |
return [shortDirections[dealer], handString].join(':') | |
} | |
function sortCardsString (cardsString) { | |
return cardsString | |
.split('') | |
.sort((cardA, cardB) => ranksSorted.indexOf(cardA) - ranksSorted.indexOf(cardB)) | |
.join('') | |
} | |
export function buildPbnFromHand ({ boardNumber, hands }) { | |
const dealer = dealerCompute(boardNumber) | |
const sortOrder = pbnDirectionCardsOrder[shortDirections[dealer]] | |
const handsetObjects = hands.reduce((acc, hand) => { | |
const { direction } = hand | |
acc[shortDirections[direction]] = { | |
S: sortCardsString(hand.spades), | |
H: sortCardsString(hand.hearts), | |
D: sortCardsString(hand.diamonds), | |
C: sortCardsString(hand.clubs) | |
} | |
return acc | |
}, {}) | |
const handsetString = Object.entries(handsetObjects) | |
.sort((directionA, directionB) => sortOrder.indexOf(directionA) - sortOrder.indexOf(directionB)) | |
.map(([_, { S, H, D, C }]) => [S, H, D, C].join('.')) | |
.join(' ') | |
return { boardNumber, pbn: [shortDirections[dealer], handsetString].join(':') } | |
} | |
export default buildPbn |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import dds from 'dds-node-adapter' | |
import buildPbn from './pbn' | |
import { vulnerablityCompute, dealerCompute } from 'results/utils/hands' | |
import { vulnerabilities } from 'results/constants' | |
const suitsToDDS = { | |
C: dds.SUIT_CLUBS, | |
D: dds.SUIT_DIAMONDS, | |
H: dds.SUIT_HEARTS, | |
S: dds.SUIT_SPADES, | |
NT: dds.SUIT_NOTRUMPS | |
} | |
const directionToDDS = { | |
N: dds.HAND_NORTH, | |
S: dds.HAND_SOUTH, | |
W: dds.HAND_WEST, | |
E: dds.HAND_EAST | |
} | |
const ddsToSuit = { | |
[dds.SUIT_CLUBS]: 'C', | |
[dds.SUIT_DIAMONDS]: 'D', | |
[dds.SUIT_HEARTS]: 'H', | |
[dds.SUIT_SPADES]: 'S', | |
[dds.SUIT_NOTRUMPS]: 'NT' | |
} | |
const cardsToDDS = { | |
2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, T: 10, J: 11, Q: 12, K: 13, A: 14 | |
} | |
const ddsToCards = { | |
2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, 10: 'T', 11: 'J', 12: 'Q', 13: 'K', 14: 'A' | |
} | |
function decodeCardHolding (cardHoldingInteger) { | |
return Array.from(cardHoldingInteger.toString(2)) | |
.reverse() | |
.reduce((memo, bitString, index) => bitString === '0' ? memo : memo.concat(index), []) | |
} | |
export function evaluateNextMove ({ boardNumber, cardHolding, trump, first, currentTrick }) { | |
const deal = { | |
trump: suitsToDDS[trump], | |
first: directionToDDS[first], | |
currentTrickRank: currentTrick.map(c => cardsToDDS[c.rank]), | |
currentTrickSuit: currentTrick.map(c => suitsToDDS[c.suit]), | |
remainCards: buildPbn({ boardNumber, cardHolding }) | |
} | |
const options = { | |
target: dds.TARGET_MAXIMUM, | |
solutions: dds.SOLUTION_FULL, | |
mode: dds.MODE_AUTO_SEARCH | |
} | |
return dds.solveBoard(deal, options) | |
.then(({ suit, rank, equals, score }) => { | |
return rank.filter(r => r > 0) | |
.reduce((memo, r, i) => { | |
memo.push({ suit: suit[i], rank: r, score: score[i] }) | |
if (equals[i] > 0) { | |
decodeCardHolding(equals[i]).forEach(r => { | |
memo.push({ suit: suit[i], rank: r, score: score[i] }) | |
}) | |
} | |
return memo | |
}, []) | |
.map(cardWithScore => ({ | |
card: `${ddsToCards[cardWithScore.rank]}${ddsToSuit[cardWithScore.suit]}`, | |
score: cardWithScore.score | |
})) | |
}) | |
.catch(err => { throw err }) | |
} | |
const vulnerabilityToDDS = { | |
[vulnerabilities.NONE]: dds.VULNERABLE_NONE, | |
[vulnerabilities.ALL]: dds.VULNERABLE_BOTH, | |
[vulnerabilities.NS]: dds.VULNERABLE_NS, | |
[vulnerabilities.EW]: dds.VULNERABLE_EW | |
} | |
export async function calculateMinimaxTable ({ pbn, cardHolding, boardNumber }) { | |
if (!pbn) { | |
pbn = buildPbn({ cardHolding, boardNumber }) | |
} | |
const resultTable = await dds.calcResultTable(pbn) | |
const par = await dds.par(resultTable, vulnerabilityToDDS[vulnerablityCompute(boardNumber)]) | |
return { par, resultTable } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment