diff --git a/.eslintrc.js b/.eslintrc.js index 2567d5f9..d890be8b 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,24 +1,24 @@ -module.exports = { - env: { - browser: true, - es2020: true, - }, - extends: [ - 'airbnb-base', - ], - parserOptions: { - ecmaVersion: 11, - }, - rules: { - // Don't enforce control flow closing curly brace needs to be - // on same line as next control flow opening statement - 'brace-style': 'off', - // Disable linebreak style to prevent ESLint errors on Windows line endings - // https://eslint.org/docs/rules/linebreak-style - 'linebreak-style': 'off', - // Allow console for students to debug - 'no-console': 'off', - // Allow function param reassign for array or object elements or properties - 'no-param-reassign': ['error', { props: false }], - }, -}; +module.exports = { + env: { + browser: true, + es2020: true, + }, + extends: [ + 'airbnb-base', + ], + parserOptions: { + ecmaVersion: 11, + }, + rules: { + // Don't enforce control flow closing curly brace needs to be + // on same line as next control flow opening statement + 'brace-style': 'off', + // Disable linebreak style to prevent ESLint errors on Windows line endings + // https://eslint.org/docs/rules/linebreak-style + 'linebreak-style': 'off', + // Allow console for students to debug + 'no-console': 'off', + // Allow function param reassign for array or object elements or properties + 'no-param-reassign': ['error', { props: false }], + }, +}; diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 600afc3b..d3b8f87f 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,17 +1,17 @@ -Please fill out the survey before submitting the pull request. Thanks! - -🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀 - -How many hours did you spend on this assignment? - -Please fill in one error and/or error message you received while working on this assignment. - -What part of the assignment did you spend the most time on? - -Comfort Level (1-5): - -Completeness Level (1-5): - -What did you think of this deliverable? - -Is there anything in this code that you feel pleased about? +Please fill out the survey before submitting the pull request. Thanks! + +🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀 + +How many hours did you spend on this assignment? + +Please fill in one error and/or error message you received while working on this assignment. + +What part of the assignment did you spend the most time on? + +Comfort Level (1-5): + +Completeness Level (1-5): + +What did you think of this deliverable? + +Is there anything in this code that you feel pleased about? diff --git a/.gitignore b/.gitignore index 1a04d2b9..93ed6693 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ -# File that sometimes appears on MacOS -.DS_Store - -# Dependency directories -node_modules/ +# File that sometimes appears on MacOS +.DS_Store + +# Dependency directories +node_modules/ diff --git a/.vscode/settings.json b/.vscode/settings.json index 202a1c13..68f92937 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,14 +1,14 @@ -{ - "editor.defaultFormatter": "esbenp.prettier-vscode", - "[javascript]": { - "editor.defaultFormatter": "dbaeumer.vscode-eslint" - }, - "editor.formatOnSave": true, - "editor.formatOnPaste": true, - "editor.minimap.enabled": false, - "editor.tabSize": 2, - "editor.wordWrap": "on", - "eslint.format.enable": true, - "eslint.lintTask.enable": true, - "eslint.migration.2_x": "off" -} +{ + "editor.defaultFormatter": "esbenp.prettier-vscode", + "[javascript]": { + "editor.defaultFormatter": "dbaeumer.vscode-eslint" + }, + "editor.formatOnSave": true, + "editor.formatOnPaste": true, + "editor.minimap.enabled": false, + "editor.tabSize": 2, + "editor.wordWrap": "on", + "eslint.format.enable": true, + "eslint.lintTask.enable": true, + "eslint.migration.2_x": "off" +} diff --git a/README.md b/README.md index 1d3a8a65..03e3ce3d 100644 --- a/README.md +++ b/README.md @@ -1 +1,7 @@ -# Rocket Academy Coding Bootcamp: Video Poker +# Rocket Academy Coding Bootcamp: Video Poker + +Video Poker is single-player Poker where we try to optimise our score by getting the best possible hands. The gameplay is as follows. + +1. The user starts with 100 points. +2. When they click the "Deal" button the computer deals a hand of 5 cards. The user can choose any number of their cards to replace with new, random cards. +3. After the user finishes replacing cards, the game assigns points based on the resulting hand. diff --git a/images/cards.zip b/images/cards.zip new file mode 100644 index 00000000..9ece11a0 Binary files /dev/null and b/images/cards.zip differ diff --git a/images/cards/10_of_clubs.png b/images/cards/10_of_clubs.png new file mode 100644 index 00000000..18af741d Binary files /dev/null and b/images/cards/10_of_clubs.png differ diff --git a/images/cards/10_of_diamonds.png b/images/cards/10_of_diamonds.png new file mode 100644 index 00000000..3bbc4e06 Binary files /dev/null and b/images/cards/10_of_diamonds.png differ diff --git a/images/cards/10_of_hearts.png b/images/cards/10_of_hearts.png new file mode 100644 index 00000000..3eb83d72 Binary files /dev/null and b/images/cards/10_of_hearts.png differ diff --git a/images/cards/10_of_spades.png b/images/cards/10_of_spades.png new file mode 100644 index 00000000..0b3d2947 Binary files /dev/null and b/images/cards/10_of_spades.png differ diff --git a/images/cards/2_of_clubs.png b/images/cards/2_of_clubs.png new file mode 100644 index 00000000..291ed975 Binary files /dev/null and b/images/cards/2_of_clubs.png differ diff --git a/images/cards/2_of_diamonds.png b/images/cards/2_of_diamonds.png new file mode 100644 index 00000000..4deee7cc Binary files /dev/null and b/images/cards/2_of_diamonds.png differ diff --git a/images/cards/2_of_hearts.png b/images/cards/2_of_hearts.png new file mode 100644 index 00000000..75a014f3 Binary files /dev/null and b/images/cards/2_of_hearts.png differ diff --git a/images/cards/2_of_spades.png b/images/cards/2_of_spades.png new file mode 100644 index 00000000..1ce0ffe8 Binary files /dev/null and b/images/cards/2_of_spades.png differ diff --git a/images/cards/3_of_clubs.png b/images/cards/3_of_clubs.png new file mode 100644 index 00000000..076ab318 Binary files /dev/null and b/images/cards/3_of_clubs.png differ diff --git a/images/cards/3_of_diamonds.png b/images/cards/3_of_diamonds.png new file mode 100644 index 00000000..8ee0b4b9 Binary files /dev/null and b/images/cards/3_of_diamonds.png differ diff --git a/images/cards/3_of_hearts.png b/images/cards/3_of_hearts.png new file mode 100644 index 00000000..8e74673f Binary files /dev/null and b/images/cards/3_of_hearts.png differ diff --git a/images/cards/3_of_spades.png b/images/cards/3_of_spades.png new file mode 100644 index 00000000..f9e06b4f Binary files /dev/null and b/images/cards/3_of_spades.png differ diff --git a/images/cards/4_of_clubs.png b/images/cards/4_of_clubs.png new file mode 100644 index 00000000..8be9e089 Binary files /dev/null and b/images/cards/4_of_clubs.png differ diff --git a/images/cards/4_of_diamonds.png b/images/cards/4_of_diamonds.png new file mode 100644 index 00000000..70e82e83 Binary files /dev/null and b/images/cards/4_of_diamonds.png differ diff --git a/images/cards/4_of_hearts.png b/images/cards/4_of_hearts.png new file mode 100644 index 00000000..ceecbfe0 Binary files /dev/null and b/images/cards/4_of_hearts.png differ diff --git a/images/cards/4_of_spades.png b/images/cards/4_of_spades.png new file mode 100644 index 00000000..95abe3e7 Binary files /dev/null and b/images/cards/4_of_spades.png differ diff --git a/images/cards/5_of_clubs.png b/images/cards/5_of_clubs.png new file mode 100644 index 00000000..bde97776 Binary files /dev/null and b/images/cards/5_of_clubs.png differ diff --git a/images/cards/5_of_diamonds.png b/images/cards/5_of_diamonds.png new file mode 100644 index 00000000..bb925255 Binary files /dev/null and b/images/cards/5_of_diamonds.png differ diff --git a/images/cards/5_of_hearts.png b/images/cards/5_of_hearts.png new file mode 100644 index 00000000..d923456f Binary files /dev/null and b/images/cards/5_of_hearts.png differ diff --git a/images/cards/5_of_spades.png b/images/cards/5_of_spades.png new file mode 100644 index 00000000..53a1aad2 Binary files /dev/null and b/images/cards/5_of_spades.png differ diff --git a/images/cards/6_of_clubs.png b/images/cards/6_of_clubs.png new file mode 100644 index 00000000..a9660a03 Binary files /dev/null and b/images/cards/6_of_clubs.png differ diff --git a/images/cards/6_of_diamonds.png b/images/cards/6_of_diamonds.png new file mode 100644 index 00000000..78a80ad0 Binary files /dev/null and b/images/cards/6_of_diamonds.png differ diff --git a/images/cards/6_of_hearts.png b/images/cards/6_of_hearts.png new file mode 100644 index 00000000..361643ef Binary files /dev/null and b/images/cards/6_of_hearts.png differ diff --git a/images/cards/6_of_spades.png b/images/cards/6_of_spades.png new file mode 100644 index 00000000..40242a71 Binary files /dev/null and b/images/cards/6_of_spades.png differ diff --git a/images/cards/7_of_clubs.png b/images/cards/7_of_clubs.png new file mode 100644 index 00000000..9d6b5455 Binary files /dev/null and b/images/cards/7_of_clubs.png differ diff --git a/images/cards/7_of_diamonds.png b/images/cards/7_of_diamonds.png new file mode 100644 index 00000000..6ad5f15b Binary files /dev/null and b/images/cards/7_of_diamonds.png differ diff --git a/images/cards/7_of_hearts.png b/images/cards/7_of_hearts.png new file mode 100644 index 00000000..19b89a2e Binary files /dev/null and b/images/cards/7_of_hearts.png differ diff --git a/images/cards/7_of_spades.png b/images/cards/7_of_spades.png new file mode 100644 index 00000000..b9f1b93d Binary files /dev/null and b/images/cards/7_of_spades.png differ diff --git a/images/cards/8_of_clubs.png b/images/cards/8_of_clubs.png new file mode 100644 index 00000000..cec743cb Binary files /dev/null and b/images/cards/8_of_clubs.png differ diff --git a/images/cards/8_of_diamonds.png b/images/cards/8_of_diamonds.png new file mode 100644 index 00000000..ed129512 Binary files /dev/null and b/images/cards/8_of_diamonds.png differ diff --git a/images/cards/8_of_hearts.png b/images/cards/8_of_hearts.png new file mode 100644 index 00000000..fb39723c Binary files /dev/null and b/images/cards/8_of_hearts.png differ diff --git a/images/cards/8_of_spades.png b/images/cards/8_of_spades.png new file mode 100644 index 00000000..b6b3b381 Binary files /dev/null and b/images/cards/8_of_spades.png differ diff --git a/images/cards/9_of_clubs.png b/images/cards/9_of_clubs.png new file mode 100644 index 00000000..2174db58 Binary files /dev/null and b/images/cards/9_of_clubs.png differ diff --git a/images/cards/9_of_diamonds.png b/images/cards/9_of_diamonds.png new file mode 100644 index 00000000..0b933fb0 Binary files /dev/null and b/images/cards/9_of_diamonds.png differ diff --git a/images/cards/9_of_hearts.png b/images/cards/9_of_hearts.png new file mode 100644 index 00000000..7b196d6d Binary files /dev/null and b/images/cards/9_of_hearts.png differ diff --git a/images/cards/9_of_spades.png b/images/cards/9_of_spades.png new file mode 100644 index 00000000..3c3b5ffb Binary files /dev/null and b/images/cards/9_of_spades.png differ diff --git a/images/cards/ace_of_clubs.png b/images/cards/ace_of_clubs.png new file mode 100644 index 00000000..42bf5ec9 Binary files /dev/null and b/images/cards/ace_of_clubs.png differ diff --git a/images/cards/ace_of_diamonds.png b/images/cards/ace_of_diamonds.png new file mode 100644 index 00000000..79cd3b8a Binary files /dev/null and b/images/cards/ace_of_diamonds.png differ diff --git a/images/cards/ace_of_hearts.png b/images/cards/ace_of_hearts.png new file mode 100644 index 00000000..b4221240 Binary files /dev/null and b/images/cards/ace_of_hearts.png differ diff --git a/images/cards/ace_of_spades.png b/images/cards/ace_of_spades.png new file mode 100644 index 00000000..103f56d1 Binary files /dev/null and b/images/cards/ace_of_spades.png differ diff --git a/images/cards/back.png b/images/cards/back.png new file mode 100644 index 00000000..84575a2a Binary files /dev/null and b/images/cards/back.png differ diff --git a/images/cards/jack_of_clubs.png b/images/cards/jack_of_clubs.png new file mode 100644 index 00000000..5e003be2 Binary files /dev/null and b/images/cards/jack_of_clubs.png differ diff --git a/images/cards/jack_of_diamonds.png b/images/cards/jack_of_diamonds.png new file mode 100644 index 00000000..131a9773 Binary files /dev/null and b/images/cards/jack_of_diamonds.png differ diff --git a/images/cards/jack_of_hearts.png b/images/cards/jack_of_hearts.png new file mode 100644 index 00000000..bf342bcb Binary files /dev/null and b/images/cards/jack_of_hearts.png differ diff --git a/images/cards/jack_of_spades.png b/images/cards/jack_of_spades.png new file mode 100644 index 00000000..f539c19c Binary files /dev/null and b/images/cards/jack_of_spades.png differ diff --git a/images/cards/king_of_clubs.png b/images/cards/king_of_clubs.png new file mode 100644 index 00000000..68e57747 Binary files /dev/null and b/images/cards/king_of_clubs.png differ diff --git a/images/cards/king_of_diamonds.png b/images/cards/king_of_diamonds.png new file mode 100644 index 00000000..e21d6a0a Binary files /dev/null and b/images/cards/king_of_diamonds.png differ diff --git a/images/cards/king_of_hearts.png b/images/cards/king_of_hearts.png new file mode 100644 index 00000000..1d3c468d Binary files /dev/null and b/images/cards/king_of_hearts.png differ diff --git a/images/cards/king_of_spades.png b/images/cards/king_of_spades.png new file mode 100644 index 00000000..2edbbc14 Binary files /dev/null and b/images/cards/king_of_spades.png differ diff --git a/images/cards/queen_of_clubs.png b/images/cards/queen_of_clubs.png new file mode 100644 index 00000000..7be5f9a9 Binary files /dev/null and b/images/cards/queen_of_clubs.png differ diff --git a/images/cards/queen_of_diamonds.png b/images/cards/queen_of_diamonds.png new file mode 100644 index 00000000..928f6501 Binary files /dev/null and b/images/cards/queen_of_diamonds.png differ diff --git a/images/cards/queen_of_hearts.png b/images/cards/queen_of_hearts.png new file mode 100644 index 00000000..21839e68 Binary files /dev/null and b/images/cards/queen_of_hearts.png differ diff --git a/images/cards/queen_of_spades.png b/images/cards/queen_of_spades.png new file mode 100644 index 00000000..7983d034 Binary files /dev/null and b/images/cards/queen_of_spades.png differ diff --git a/images/logo.png b/images/logo.png new file mode 100644 index 00000000..61de30d1 Binary files /dev/null and b/images/logo.png differ diff --git a/index.html b/index.html new file mode 100644 index 00000000..a6714ecd --- /dev/null +++ b/index.html @@ -0,0 +1,203 @@ + + + + + + + + + + Shaz's Video Poker Game! + + + + + + + + + +
+
+
+ +

Video Poker

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
12345
Royal Flush25050075010004000
Straight Flush50100150200250
Four Of A Kind255075100125
Full House918273645
Flush612182430
Straight48121620
Three Of A Kind3691215
Two Pair246810
+
+
+
+ Start by pressing Bet 1 or + Bet 5 and pressing + Deal after. +
+ + +
+
+
+
+ + + + +
+
+
+
+ Bet: 0 + / + Credits: 100 +
+
+
+
+ + + + + + + + diff --git a/package-lock.json b/package-lock.json index 7c1c09b9..fd1fd5d8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1029,6 +1029,11 @@ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, + "nes.css": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/nes.css/-/nes.css-2.3.0.tgz", + "integrity": "sha512-lCFZs9vj3f5RVdbvTL/kSxiYsOARwSeAdJaMNo+bCgmWOO9x8ay7QpT4yQVKHy3r5Dttzd0uqVdpt3fvvx6EpQ==" + }, "normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", diff --git a/package.json b/package.json index 1bf85b18..ba5ab359 100644 --- a/package.json +++ b/package.json @@ -1,24 +1,27 @@ -{ - "name": "video-poker-swe1", - "version": "1.0.0", - "description": "SWE1 Video Poker", - "main": "script.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/rocketacademy/video-poker-swe1.git" - }, - "author": "", - "license": "ISC", - "bugs": { - "url": "https://github.com/rocketacademy/video-poker-swe1/issues" - }, - "homepage": "https://github.com/rocketacademy/video-poker-swe1#readme", - "devDependencies": { - "eslint": "^7.6.0", - "eslint-config-airbnb-base": "^14.2.0", - "eslint-plugin-import": "^2.22.0" - } -} +{ + "name": "video-poker-swe1", + "version": "1.0.0", + "description": "SWE1 Video Poker", + "main": "script.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/rocketacademy/video-poker-swe1.git" + }, + "author": "", + "license": "ISC", + "bugs": { + "url": "https://github.com/rocketacademy/video-poker-swe1/issues" + }, + "homepage": "https://github.com/rocketacademy/video-poker-swe1#readme", + "devDependencies": { + "eslint": "^7.6.0", + "eslint-config-airbnb-base": "^14.2.0", + "eslint-plugin-import": "^2.22.0" + }, + "dependencies": { + "nes.css": "^2.3.0" + } +} diff --git a/scripts/checkCombination.js b/scripts/checkCombination.js new file mode 100644 index 00000000..28cc173b --- /dev/null +++ b/scripts/checkCombination.js @@ -0,0 +1,1654 @@ +/** + * + * @param {Number} number of items to be rearranged + * @returns {Number} number of permutations to arrange num distinct objects into an ordered sequence + */ +const factorialize = (num) => { + if (num < 0) return -1; + if (num === 0) return 1; + return (num * factorialize(num - 1)); +}; + +/** + * + * @param {Number} [numberOfCardsLeft] - number of cards still left in the deck yet to be drawn + * @param {Number} [cardsToDraw] - number of cards to be drawn + * @returns {Number} number of ways to choose a sample of [cardsToDraw] cards from a set of [numberOfCardsLeft] cards where order does not matter and replacements are allowed. + */ +const countTotalCombinations = (numberOfCardsLeft, cardsToDraw) => { + const numerator = factorialize(numberOfCardsLeft); + const denominator = (factorialize(numberOfCardsLeft - cardsToDraw) * factorialize(cardsToDraw)); + + return numerator / denominator; +}; + +/** + * + * @returns {Number} number of royal flush combinations that can be achieved with cards being held + */ +const checkRoyalFlushCombinations = () => { + const royalResult = isHeldCardsRoyal(stats.hand); + const flushResult = isHeldCardsSameSuit(stats.hand); + + // check whether same suit first + if (flushResult.result && royalResult.result) { + // check what are the remaining cards to draw to get a royal flush + if (royalResult.royalHand.ace !== 1) { + // check if card is available + if (cardsLeft.ace[flushResult.suit] !== 1) { + return 0; + } + } + + if (royalResult.royalHand.king !== 1) { + // check if card is available + if (cardsLeft.king[flushResult.suit] !== 1) { + return 0; + } + } + + if (royalResult.royalHand.queen !== 1) { + // check if card is available + if (cardsLeft.queen[flushResult.suit] !== 1) { + return 0; + } + } + + if (royalResult.royalHand.jack !== 1) { + // check if card is available + if (cardsLeft.jack[flushResult.suit] !== 1) { + return 0; + } + } + + if (royalResult.royalHand[10] !== 1) { + // check if card is available + if (cardsLeft[10][flushResult.suit] !== 1) { + return 0; + } + } + + return 1; + } + return 0; +}; + +/** + * + * @returns {Number} number of straight flush combinations that can be achieved with cards being held + */ +const checkStraightFlushCombinations = () => { + const flushResult = isHeldCardsSameSuit(stats.hand); + const withinStraightResult = isHeldCardsWithinStraight(stats.hand); + + let combinations = 0; + + if (flushResult.result && withinStraightResult.result) { + const { straightHand } = withinStraightResult; + const { diff } = withinStraightResult; + const { suit } = flushResult; + + // check all the different cards i need to draw + // if i have rank 1 and 5, 1 and 5 are the limits (diff = 4) + // and i can only find 3, 4 ane 5 + // if i have rank 2 and 5, 1 and 6 are the limits (diff = 3) + // e.g. 1,2,3,4,5 or 2,3,4,5,6 + // if i have rank 5 and 7, 3 and 9 are the limits (diff = 2) + // e.g. 3,4,5,6,7 or 5,6,7,8,9 + // if i have rank 5 and 6, 2 and 9 are the limits (diff = 1) + // e.g. 2,3,4,5,6,7 or 5,6,7,8,9 + + const rankArray = Object.keys(straightHand); + + if (diff === 4) { + let straightPossible = true; + + const firstRank = parseInt(rankArray[0], 10); + + for (let i = 1; i < 5; i += 1) { + if (rankArray.indexOf((firstRank + i).toString()) === -1) { + // current rank is not in held cards + // find in cardsLeft + if (cardsLeft[(firstRank + i).toString()][suit] === 0) { + straightPossible = false; + } + } + } + + if (straightPossible) { + combinations += 1; + } + } else if (diff === 3) { + let straightPossible = true; + + const firstRank1 = parseInt(rankArray[0], 10); + const lastRank1 = firstRank1 + 4; + + for (let i = firstRank1; i <= lastRank1; i += 1) { + if (straightHand[i] === undefined) { + if (i === 1) { + if (cardsLeft.ace[suit] === 0) { + straightPossible = false; + break; + } + } else if (i === 11) { + if (cardsLeft.jack[suit] === 0) { + straightPossible = false; + break; + } + } else if (i === 12) { + if (cardsLeft.queen[suit] === 0) { + straightPossible = false; + break; + } + } else if (i === 13) { + if (cardsLeft.king[suit] === 0) { + straightPossible = false; + break; + } + } else if (i > 13) { + straightPossible = false; + break; + } else if (cardsLeft[i][suit] === 0) { + straightPossible = false; + break; + } + } + } + + if (straightPossible) { + combinations += 1; + } + + straightPossible = true; + + if (parseInt(rankArray[0], 10) - 1 > 0) { + const firstRank2 = parseInt(rankArray[0], 10) - 1; + const lastRank2 = firstRank2 + 4; + + for (let i = firstRank2; i <= lastRank2; i += 1) { + if (straightHand[i] === undefined) { + if (i === 1) { + if (cardsLeft.ace[suit] === 0) { + straightPossible = false; + break; + } + } else if (i === 11) { + if (cardsLeft.jack[suit] === 0) { + straightPossible = false; + break; + } + } else if (i === 12) { + if (cardsLeft.queen[suit] === 0) { + straightPossible = false; + break; + } + } else if (i === 13) { + if (cardsLeft.king[suit] === 0) { + straightPossible = false; + break; + } + } else if (i > 13) { + straightPossible = false; + break; + } else if (cardsLeft[i][suit] === 0) { + straightPossible = false; + break; + } + } + } + + if (straightPossible) { + combinations += 1; + } + } + } else if (diff === 2) { + let straightPossible = true; + + const firstRank1 = parseInt(rankArray[0], 10) - 1; + const lastRank1 = firstRank1 + 4; + + for (let i = firstRank1; i <= lastRank1; i += 1) { + if (straightHand[i] === undefined) { + if (i === 1) { + if (cardsLeft.ace[suit] === 0) { + straightPossible = false; + break; + } + } else if (i === 11) { + if (cardsLeft.jack[suit] === 0) { + straightPossible = false; + break; + } + } else if (i === 12) { + if (cardsLeft.queen[suit] === 0) { + straightPossible = false; + break; + } + } else if (i === 13) { + if (cardsLeft.king[suit] === 0) { + straightPossible = false; + break; + } + } else if (i > 13) { + straightPossible = false; + break; + } else if (cardsLeft[i][suit] === 0) { + straightPossible = false; + break; + } + } + } + + if (straightPossible) { + combinations += 1; + } + + straightPossible = true; + + if (parseInt(rankArray[0], 10) - 1 > 0) { + const firstRank2 = parseInt(rankArray[0], 10) - 1; + const lastRank2 = firstRank2 + 4; + + for (let i = firstRank2; i <= lastRank2; i += 1) { + if (straightHand[i] === undefined) { + if (i === 1) { + if (cardsLeft.ace[suit] === 0) { + straightPossible = false; + break; + } + } else if (i === 11) { + if (cardsLeft.jack[suit] === 0) { + straightPossible = false; + break; + } + } else if (i === 12) { + if (cardsLeft.queen[suit] === 0) { + straightPossible = false; + break; + } + } else if (i === 13) { + if (cardsLeft.king[suit] === 0) { + straightPossible = false; + break; + } + } else if (i > 13) { + straightPossible = false; + break; + } else if (cardsLeft[i][suit] === 0) { + straightPossible = false; + break; + } + } + } + + if (straightPossible) { + combinations += 1; + } + } + + straightPossible = true; + + if (parseInt(rankArray[0], 10) - 2 > 0) { + const firstRank3 = parseInt(rankArray[0], 10) - 2; + const lastRank3 = firstRank3 + 4; + + for (let i = firstRank3; i <= lastRank3; i += 1) { + if (straightHand[i] === undefined) { + if (i === 1) { + if (cardsLeft.ace[suit] === 0) { + straightPossible = false; + break; + } + } else if (i === 11) { + if (cardsLeft.jack[suit] === 0) { + straightPossible = false; + break; + } + } else if (i === 12) { + if (cardsLeft.queen[suit] === 0) { + straightPossible = false; + break; + } + } else if (i === 13) { + if (cardsLeft.king[suit] === 0) { + straightPossible = false; + break; + } + } else if (i > 13) { + straightPossible = false; + break; + } else if (cardsLeft[i][suit] === 0) { + straightPossible = false; + break; + } + } + } + + if (straightPossible) { + combinations += 1; + } + } + } else if (diff === 1) { + let straightPossible = true; + + const firstRank1 = parseInt(rankArray[0], 10) - 1; + const lastRank1 = firstRank1 + 4; + + for (let i = firstRank1; i <= lastRank1; i += 1) { + if (straightHand[i] === undefined) { + if (i === 1) { + if (cardsLeft.ace[suit] === 0) { + straightPossible = false; + break; + } + } else if (i === 11) { + if (cardsLeft.jack[suit] === 0) { + straightPossible = false; + break; + } + } else if (i === 12) { + if (cardsLeft.queen[suit] === 0) { + straightPossible = false; + break; + } + } else if (i === 13) { + if (cardsLeft.king[suit] === 0) { + straightPossible = false; + break; + } + } else if (i > 13) { + straightPossible = false; + break; + } else if (cardsLeft[i][suit] === 0) { + straightPossible = false; + break; + } + } + } + + if (straightPossible) { + combinations += 1; + } + + straightPossible = true; + + if (parseInt(rankArray[0], 10) - 1 > 0) { + const firstRank2 = parseInt(rankArray[0], 10) - 1; + const lastRank2 = firstRank2 + 4; + + for (let i = firstRank2; i <= lastRank2; i += 1) { + if (straightHand[i] === undefined) { + if (i === 1) { + if (cardsLeft.ace[suit] === 0) { + straightPossible = false; + break; + } + } else if (i === 11) { + if (cardsLeft.jack[suit] === 0) { + straightPossible = false; + break; + } + } else if (i === 12) { + if (cardsLeft.queen[suit] === 0) { + straightPossible = false; + break; + } + } else if (i === 13) { + if (cardsLeft.king[suit] === 0) { + straightPossible = false; + break; + } + } else if (i > 13) { + straightPossible = false; + break; + } else if (cardsLeft[i][suit] === 0) { + straightPossible = false; + break; + } + } + } + + if (straightPossible) { + combinations += 1; + } + } + + straightPossible = true; + + if (parseInt(rankArray[0], 10) - 2 > 0) { + const firstRank3 = parseInt(rankArray[0], 10) - 2; + const lastRank3 = firstRank3 + 4; + + for (let i = firstRank3; i <= lastRank3; i += 1) { + if (straightHand[i] === undefined) { + if (i === 1) { + if (cardsLeft.ace[suit] === 0) { + straightPossible = false; + break; + } + } else if (i === 11) { + if (cardsLeft.jack[suit] === 0) { + straightPossible = false; + break; + } + } else if (i === 12) { + if (cardsLeft.queen[suit] === 0) { + straightPossible = false; + break; + } + } else if (i === 13) { + if (cardsLeft.king[suit] === 0) { + straightPossible = false; + break; + } + } else if (i > 13) { + straightPossible = false; + break; + } else if (cardsLeft[i][suit] === 0) { + straightPossible = false; + break; + } + } + } + + if (straightPossible) { + combinations += 1; + } + } + + if (parseInt(rankArray[0], 10) - 3 > 0) { + const firstRank4 = parseInt(rankArray[0], 10) - 3; + const lastRank4 = firstRank4 + 4; + + for (let i = firstRank4; i <= lastRank4; i += 1) { + if (straightHand[i] === undefined) { + if (i === 1) { + if (cardsLeft.ace[suit] === 0) { + straightPossible = false; + break; + } + } else if (i === 11) { + if (cardsLeft.jack[suit] === 0) { + straightPossible = false; + break; + } + } else if (i === 12) { + if (cardsLeft.queen[suit] === 0) { + straightPossible = false; + break; + } + } else if (i === 13) { + if (cardsLeft.king[suit] === 0) { + straightPossible = false; + break; + } + } else if (i > 13) { + straightPossible = false; + break; + } else if (cardsLeft[i][suit] === 0) { + straightPossible = false; + break; + } + } + } + + if (straightPossible) { + combinations += 1; + } + } + } else if (diff === 0) { + let straightPossible = true; + + if (parseInt(rankArray[0], 10) !== 0) { + const firstRank1 = parseInt(rankArray[0], 10); + const lastRank1 = firstRank1 + 4; + + for (let i = firstRank1; i <= lastRank1; i += 1) { + if (straightHand[i] === undefined) { + if (i === 1) { + if (cardsLeft.ace[suit] === 0) { + straightPossible = false; + break; + } + } else if (i === 11) { + if (cardsLeft.jack[suit] === 0) { + straightPossible = false; + break; + } + } else if (i === 12) { + if (cardsLeft.queen[suit] === 0) { + straightPossible = false; + break; + } + } else if (i === 13) { + if (cardsLeft.king[suit] === 0) { + straightPossible = false; + break; + } + } else if (i > 13) { + straightPossible = false; + break; + } else if (cardsLeft[i][suit] === 0) { + straightPossible = false; + break; + } + } + } + + if (straightPossible) { + combinations += 1; + } + } + + straightPossible = true; + + if (parseInt(rankArray[0], 10) - 1 > 0) { + const firstRank2 = parseInt(rankArray[0], 10) - 1; + const lastRank2 = firstRank2 + 4; + + for (let i = firstRank2; i <= lastRank2; i += 1) { + if (straightHand[i] === undefined) { + if (i === 1) { + if (cardsLeft.ace[suit] === 0) { + straightPossible = false; + break; + } + } else if (i === 11) { + if (cardsLeft.jack[suit] === 0) { + straightPossible = false; + break; + } + } else if (i === 12) { + if (cardsLeft.queen[suit] === 0) { + straightPossible = false; + break; + } + } else if (i === 13) { + if (cardsLeft.king[suit] === 0) { + straightPossible = false; + break; + } + } else if (i > 13) { + straightPossible = false; + break; + } else if (cardsLeft[i][suit] === 0) { + straightPossible = false; + break; + } + } + } + + if (straightPossible) { + combinations += 1; + } + } + + straightPossible = true; + + if (parseInt(rankArray[0], 10) - 2 > 0) { + const firstRank3 = parseInt(rankArray[0], 10) - 2; + const lastRank3 = firstRank3 + 4; + + for (let i = firstRank3; i <= lastRank3; i += 1) { + if (straightHand[i] === undefined) { + if (i === 1) { + if (cardsLeft.ace[suit] === 0) { + straightPossible = false; + break; + } + } else if (i === 11) { + if (cardsLeft.jack[suit] === 0) { + straightPossible = false; + break; + } + } else if (i === 12) { + if (cardsLeft.queen[suit] === 0) { + straightPossible = false; + break; + } + } else if (i === 13) { + if (cardsLeft.king[suit] === 0) { + straightPossible = false; + break; + } + } else if (i > 13) { + straightPossible = false; + break; + } else if (cardsLeft[i][suit] === 0) { + straightPossible = false; + break; + } + } + } + + if (straightPossible) { + combinations += 1; + } + } + + straightPossible = true; + + if (parseInt(rankArray[0], 10) - 3 > 0) { + const firstRank4 = parseInt(rankArray[0], 10) - 3; + const lastRank4 = firstRank4 + 4; + + for (let i = firstRank4; i <= lastRank4; i += 1) { + if (straightHand[i] === undefined) { + if (i === 1) { + if (cardsLeft.ace[suit] === 0) { + straightPossible = false; + break; + } + } else if (i === 11) { + if (cardsLeft.jack[suit] === 0) { + straightPossible = false; + break; + } + } else if (i === 12) { + if (cardsLeft.queen[suit] === 0) { + straightPossible = false; + break; + } + } else if (i === 13) { + if (cardsLeft.king[suit] === 0) { + straightPossible = false; + break; + } + } else if (i > 13) { + straightPossible = false; + break; + } else if (cardsLeft[i][suit] === 0) { + straightPossible = false; + break; + } + } + } + + if (straightPossible) { + combinations += 1; + } + } + + straightPossible = true; + + if (parseInt(rankArray[0], 10) - 4 > 0) { + const firstRank5 = parseInt(rankArray[0], 10) - 4; + const lastRank5 = firstRank5 + 4; + + for (let i = firstRank5; i <= lastRank5; i += 1) { + if (straightHand[i] === undefined) { + if (i === 1) { + if (cardsLeft.ace[suit] === 0) { + straightPossible = false; + break; + } + } else if (i === 11) { + if (cardsLeft.jack[suit] === 0) { + straightPossible = false; + break; + } + } else if (i === 12) { + if (cardsLeft.queen[suit] === 0) { + straightPossible = false; + break; + } + } else if (i === 13) { + if (cardsLeft.king[suit] === 0) { + straightPossible = false; + break; + } + } else if (i > 13) { + straightPossible = false; + break; + } else if (cardsLeft[i][suit] === 0) { + straightPossible = false; + break; + } + } + } + + if (straightPossible) { + combinations += 1; + } + } + } + + return combinations; + } + + return 0; +}; + +/** + * + * @returns {Number} number of two pair combinations that can be achieved with cards being held + */ +const checkTwoPairCombinations = () => { + const result = { + combinations: 0, + alreadyWin: false, + }; + let combinations = 0; + + // get the cards being held first + const twoPairHand = {}; + + for (let i = 0; i < stats.hand.length; i += 1) { + if (stats.hand[i].hold === true) { + if (twoPairHand[stats.hand[i].rank] === undefined) { + twoPairHand[stats.hand[i].rank] = 1; + } else { + twoPairHand[stats.hand[i].rank] += 1; + } + } + } + + const rankArray = Object.keys(twoPairHand); + + const twoPairHandValues = Object.values(twoPairHand); + const twoPairHandCardLeft = []; + + for (let i = 0; i < rankArray.length; i += 1) { + const rank = parseInt(rankArray[i], 10); + + const cardsLeftWithRank = getCardsLeftWithRank(rank); + + twoPairHandCardLeft.push(cardsLeftWithRank); + } + + let twoCounts = 0; + + for (let i = 0; i < twoPairHandValues.length; i += 1) { + if (twoPairHandValues[i] === 2) { + twoCounts += 1; + } + } + + if (Object.values(twoPairHand).length === 5 || rankArray.length >= 4) { + combinations = 0; + } else if (twoCounts === 2) { + result.alreadyWin = true; + combinations = 1; + } else if (rankArray.length === 3) { + const rank1Held = twoPairHandValues[0]; + const rank1Left = twoPairHandCardLeft[0]; + + const rank2Held = twoPairHandValues[1]; + const rank2Left = twoPairHandCardLeft[1]; + + const rank3Held = twoPairHandValues[2]; + const rank3Left = twoPairHandCardLeft[2]; + + if (rank1Held <= 2 && rank2Held <= 2 && rank3Held <= 2) { + + let tempCombinations = 0; + + let rank1 = parseInt(rankArray[0], 10); + + if (rank1 === 1) { + rank1 = 'ace'; + } else if (rank1 === 11) { + rank1 = 'jack'; + } else if (rank1 === 12) { + rank1 = 'queen'; + } else if (rank1 === 13) { + rank1 = 'king'; + } + + let rank2 = parseInt(rankArray[1], 10); + + if (rank2 === 1) { + rank2 = 'ace'; + } else if (rank2 === 11) { + rank2 = 'jack'; + } else if (rank2 === 12) { + rank2 = 'queen'; + } else if (rank2 === 13) { + rank2 = 'king'; + } + + let rank3 = parseInt(rankArray[1], 10); + + if (rank3 === 1) { + rank3 = 'ace'; + } else if (rank3 === 11) { + rank3 = 'jack'; + } else if (rank3 === 12) { + rank3 = 'queen'; + } else if (rank3 === 13) { + rank3 = 'king'; + } + + const cardsLeftKeys = Object.keys(cardsLeft); + const cardsLeftValues = Object.values(cardsLeft); + + // set 1: 2 of Rank A 2 of Rank B 1 of Rank C + if ((rank1Left + rank1Held >= 2) && (rank2Left + rank2Held >= 2)) { + const rank1Combinations = countTotalCombinations(rank1Left, 2 - rank1Held); + const rank2Combinations = countTotalCombinations(rank2Left, 2 - rank2Held); + + tempCombinations += (rank1Combinations * rank2Combinations); + } else { + tempCombinations = 0; + } + + combinations += tempCombinations; + + tempCombinations = 0; + + // set 2: 2 of Rank A 1 of Rank B 2 of Rank C + if ((rank1Left + rank1Held >= 2) && (rank3Left + rank3Held >= 2)) { + const rank1Combinations = countTotalCombinations(rank1Left, 2 - rank1Held); + const rank3Combinations = countTotalCombinations(rank3Left, 2 - rank3Held); + + tempCombinations += (rank1Combinations * rank3Combinations); + } else { + tempCombinations = 0; + } + + combinations += tempCombinations; + + tempCombinations = 0; + + // set 3: 1 of Rank A 2 of Rank B 2 of Rank C + if ((rank2Left + rank2Held >= 2) && (rank3Left + rank3Held >= 2)) { + const rank2Combinations = countTotalCombinations(rank2Left, 2 - rank2Held); + const rank3Combinations = countTotalCombinations(rank3Left, 2 - rank3Held); + + tempCombinations += (rank2Combinations * rank3Combinations); + } else { + tempCombinations = 0; + } + + combinations += tempCombinations; + } + } else if (rankArray.length === 2) { + const rank1Held = twoPairHandValues[0]; + const rank1Left = twoPairHandCardLeft[0]; + + const rank2Held = twoPairHandValues[1]; + const rank2Left = twoPairHandCardLeft[1]; + + if (rank1Held <= 2 && rank2Held <= 2) { + + let tempCombinations = 0; + + // if i am holding to 2 and 4 + // i need to have different conditions + + let rank1 = parseInt(rankArray[0], 10); + + if (rank1 === 1) { + rank1 = 'ace'; + } else if (rank1 === 11) { + rank1 = 'jack'; + } else if (rank1 === 12) { + rank1 = 'queen'; + } else if (rank1 === 13) { + rank1 = 'king'; + } + + let rank2 = parseInt(rankArray[1], 10); + + if (rank2 === 1) { + rank2 = 'ace'; + } else if (rank2 === 11) { + rank2 = 'jack'; + } else if (rank2 === 12) { + rank2 = 'queen'; + } else if (rank2 === 13) { + rank2 = 'king'; + } + + const cardsLeftKeys = Object.keys(cardsLeft); + const cardsLeftValues = Object.values(cardsLeft); + + // set 1: two 2s one 4 and two of other cards + if (rank1Left + rank1Held >= 2) { + const rank1Combinations = countTotalCombinations(rank1Left, 2 - rank1Held); + + for (let i = 0; i < cardsLeftKeys.length; i += 1) { + let tempCombi = 0; + if (cardsLeftKeys[i] !== rank1 && cardsLeftKeys[i] !== rank2) { + const tempCardLeftValue = getCardsLeftWithRank(cardsLeftKeys[i]); + if (tempCardLeftValue >= 2) { + tempCombi = countTotalCombinations(tempCardLeftValue, 2); + } else { + tempCombi = 0; + } + + tempCombinations += (rank1Combinations * tempCombi); + } + } + } else { + tempCombinations = 0; + } + + combinations += tempCombinations; + + tempCombinations = 0; + + // set 2: one 2 two 4s and two of other cards + if (rank2Left + rank2Held >= 2) { + const rank2Combinations = countTotalCombinations(rank2Left, 2 - rank2Held); + + for (let i = 0; i < cardsLeftKeys.length; i += 1) { + let tempCombi = 0; + if (cardsLeftKeys[i] !== rank1 && cardsLeftKeys[i] !== rank2) { + const tempCardLeftValue = getCardsLeftWithRank(cardsLeftKeys[i]); + if (tempCardLeftValue >= 2) { + tempCombi = countTotalCombinations(tempCardLeftValue, 2); + } else { + tempCombi = 0; + } + + tempCombinations += (rank2Combinations * tempCombi); + } + } + } else { + tempCombinations = 0; + } + + combinations += tempCombinations; + } + } else if (rankArray.length === 1) { + const rankHeld = twoPairHandValues[0]; + const rankLeft = twoPairHandCardLeft[0]; + + if (rankHeld <= 2) { + let rank = parseInt(rankArray[0], 10); + + if (rank === 1) { + rank = 'ace'; + } else if (rank === 11) { + rank = 'jack'; + } else if (rank === 12) { + rank = 'queen'; + } else if (rank === 13) { + rank = 'king'; + } + + const cardsLeftKeys = Object.keys(cardsLeft); + const cardsLeftValues = Object.values(cardsLeft); + + // set 1: 2 of rank 1, 2 of any other number, 1 of any other number + if ((rankLeft + rankHeld) >= 2) { + const rankCombinations = countTotalCombinations(rankLeft, 2 - rankHeld); + + for (let i = 0; i < cardsLeftKeys.length; i += 1) { + let tempCombinations = 0; + if (cardsLeftKeys[i] !== rank) { + const tempCardLeftValue = getCardsLeftWithRank(cardsLeftKeys[i]); + if (tempCardLeftValue >= 2) { + // there is enough of this second rank to fill up the second pair + tempCombinations = countTotalCombinations(tempCardLeftValue, 2); + } else { + // there is not enough of this second rank to fill up the second pair + // need to rely on third rank + tempCombinations = 0; + } + + const totalCardsLeft = 47 - tempCardLeftValue; + const remainingCombinations = countTotalCombinations(totalCardsLeft, 1); + + combinations += (rankCombinations * tempCombinations * remainingCombinations); + } + } + } else { + // set 2: 1 of rank 1, 2 of any other number, 2 of any other number + for (let i = 0; i < cardsLeftKeys.length; i += 1) { + let tempCombinations = 0; + if (cardsLeftKeys[i] !== rank) { + const tempCardLeftValue = getCardsLeftWithRank(cardsLeftKeys[i]); + if (tempCardLeftValue >= 2) { + // there is enough of this second rank to fill up the second pair + tempCombinations = countTotalCombinations(tempCardLeftValue, 2); + for (let j = 0; j < cardsLeftKeys.length; j += 1) { + if (cardsLeftKeys[j] !== cardsLeftKeys[i] && cardsLeftKeys[j] !== rank) { + const tempCardLeftValue2 = getCardsLeftWithRank(cardsLeftKeys[j]); + + if (tempCardLeftValue2 >= 2) { + tempCombinations *= countTotalCombinations(tempCardLeftValue2, 2); + } else { + tempCombinations = 0; + } + + combinations += tempCombinations; + } + } + } else { + // there is not enough of this second rank to fill up the second pair + // need to rely on third rank + tempCombinations = 0; + } + + combinations += tempCombinations; + } + } + } + } + } + + result.combinations = combinations; + return result; +}; + +/** + * + * @returns {Number} number of three of a kind combinations that can be achieved with cards being held + */ +const checkThreeOfAKindCombinations = () => { + const result = { + combinations: 0, + alreadyWin: false, + }; + let combinations = 0; + + // get the cards being held first + const threeOfAKindHand = {}; + + for (let i = 0; i < stats.hand.length; i += 1) { + if (stats.hand[i].hold === true) { + if (threeOfAKindHand[stats.hand[i].rank] === undefined) { + threeOfAKindHand[stats.hand[i].rank] = 1; + } else { + threeOfAKindHand[stats.hand[i].rank] += 1; + } + } + } + + const rankArray = Object.keys(threeOfAKindHand); + + if (Object.values(threeOfAKindHand).length >= 4) { + // if there are 3 different card ranks are being held, return 0 + combinations = 0; + } else if (Object.values(threeOfAKindHand).indexOf(3) !== -1) { + // if there are already 4 cards with the same rank being held, return 1 + combinations = 1; + result.alreadyWin = true; + } else { + for (let i = 0; i < rankArray.length; i += 1) { + const rank = parseInt(rankArray[i], 10); + const noOfCardsHeld = threeOfAKindHand[rank]; + + const noOfCardsLeft = getCardsLeftWithRank(rank); + + if (noOfCardsHeld + noOfCardsLeft >= 3) { + combinations += 1; + } + } + } + + result.combinations = combinations; + + return result; +}; + +/** + * + * @returns {Number} number of four of a kind combinations that can be achieved with cards being held + */ +const checkFourOfAKindCombinations = () => { + const result = { + combinations: 0, + alreadyWin: false, + }; + let combinations = 0; + + // get the cards being held first + const fourOfAKindHand = {}; + + for (let i = 0; i < stats.hand.length; i += 1) { + if (stats.hand[i].hold === true) { + if (fourOfAKindHand[stats.hand[i].rank] === undefined) { + fourOfAKindHand[stats.hand[i].rank] = 1; + } else { + fourOfAKindHand[stats.hand[i].rank] += 1; + } + } + } + + const rankArray = Object.keys(fourOfAKindHand); + + if (Object.values(fourOfAKindHand).length >= 3) { + // if there are 3 different card ranks are being held, return 0 + combinations = 0; + } else if (Object.values(fourOfAKindHand).indexOf(4) !== -1) { + // if there are already 4 cards with the same rank being held, return 1 + combinations = 1; + result.alreadyWin = true; + } else { + for (let i = 0; i < rankArray.length; i += 1) { + const rank = parseInt(rankArray[i], 10); + const noOfCardsHeld = fourOfAKindHand[rank]; + + const noOfCardsLeft = getCardsLeftWithRank(rank); + + if (noOfCardsHeld + noOfCardsLeft === 4) { + combinations += 1; + } + } + } + result.combinations = combinations; + + return result; +}; + +/** + * + * @returns {Number} number of full house combinations that can be achieved with cards being held + */ +const checkFullHouseCombinations = () => { + const result = { + combinations: 0, + alreadyWin: false, + }; + let combinations = 0; + + // get the cards being held first + const fullHouseHand = {}; + + for (let i = 0; i < stats.hand.length; i += 1) { + if (stats.hand[i].hold === true) { + if (fullHouseHand[stats.hand[i].rank] === undefined) { + if (stats.hand[i].rank === 11) { + fullHouseHand.jack = 1; + } else if (stats.hand[i].rank === 12) { + fullHouseHand.queen = 1; + } else if (stats.hand[i].rank === 13) { + fullHouseHand.king = 1; + } else if (stats.hand[i].rank === 1) { + fullHouseHand.ace = 1; + } else { + fullHouseHand[stats.hand[i].rank] = 1; + } + } else if (stats.hand[i].rank === 11) { + fullHouseHand.jack += 1; + } else if (stats.hand[i].rank === 12) { + fullHouseHand.queen += 1; + } else if (stats.hand[i].rank === 13) { + fullHouseHand.king += 1; + } else if (stats.hand[i].rank === 1) { + fullHouseHand.ace += 1; + } else { + fullHouseHand[stats.hand[i].rank] += 1; + } + } + } + + const rankArray = Object.keys(fullHouseHand); + + if (rankArray.length >= 3) { + combinations = 0; + } else if (rankArray.length === 2) { + // given the two different ranks A and B, i need to find out + // different combinations of 3 As 2 Bs and 2 As 3 Bs. + + const rank1 = rankArray[0]; + const noOfRank1CardsHeld = fullHouseHand[rank1]; + const noOfRank1CardsLeft = getCardsLeftWithRank(rank1); + + const rank2 = rankArray[1]; + const noOfRank2CardsHeld = fullHouseHand[rank2]; + const noOfRank2CardsLeft = getCardsLeftWithRank(rank2); + + // 3 of Rank1Cards 2 of Rank2Cards + if (noOfRank1CardsHeld === 3) { + if (noOfRank2CardsLeft >= (2 - noOfRank2CardsHeld)) { + combinations += countTotalCombinations(noOfRank2CardsLeft, 2 - noOfRank2CardsHeld); + } + } else if (noOfRank1CardsHeld < 3) { + if (noOfRank1CardsLeft >= (3 - noOfRank1CardsHeld)) { + const rank1TotalCombinations = countTotalCombinations(noOfRank1CardsLeft, + 3 - noOfRank1CardsHeld); + if (noOfRank2CardsLeft >= (2 - noOfRank2CardsHeld)) { + combinations += (rank1TotalCombinations + * countTotalCombinations(noOfRank2CardsLeft, 2 - noOfRank2CardsHeld)); + } + } + } + + // 2 of Rank1Cards 3 of Rank2Cards + if (noOfRank1CardsHeld === 2) { + if (noOfRank2CardsLeft >= (3 - noOfRank2CardsHeld)) { + combinations += countTotalCombinations(noOfRank2CardsLeft, 3 - noOfRank2CardsHeld); + } + } else if (noOfRank1CardsHeld < 2) { + if (noOfRank1CardsLeft >= (2 - noOfRank1CardsHeld)) { + const rank1TotalCombinations = countTotalCombinations(noOfRank1CardsLeft, + 2 - noOfRank1CardsHeld); + if (noOfRank2CardsLeft >= (3 - noOfRank2CardsHeld)) { + combinations += (rank1TotalCombinations + * countTotalCombinations(noOfRank2CardsLeft, 3 - noOfRank2CardsHeld)); + } + } + } + } else if (rankArray.length === 1) { + // if there is only 1 rank A, i need to find out + // different combinations of 3 As 2 Of Everything Else and + // 2 As 3 Of Everything Else + + const rank1 = rankArray[0]; + const noOfRank1CardsHeld = fullHouseHand[rank1]; + const noOfRank1CardsLeft = getCardsLeftWithRank(rank1); + const totalRank1Cards = noOfRank1CardsHeld + noOfRank1CardsLeft; + + const cardsLeftKeys = Object.keys(cardsLeft); + const cardsLeftValues = Object.values(cardsLeft); + + for (let i = 0; i < cardsLeftValues.length; i += 1) { + cardsLeftValues[i] = getCardsLeftWithRank(cardsLeftKeys[i]); + } + + // 3 of Rank1Cards 2 of Rank2Cards + if (noOfRank1CardsHeld === 3) { + for (let i = 0; i < cardsLeftKeys.length; i += 1) { + if (cardsLeftValues[i] >= 2) { + combinations += countTotalCombinations(cardsLeftValues[i], 2); + } + } + } else if (noOfRank1CardsHeld < 3) { + if (noOfRank1CardsLeft >= (3 - noOfRank1CardsHeld)) { + const rank1TotalCombinations = countTotalCombinations(noOfRank1CardsLeft, + 3 - noOfRank1CardsHeld); + + for (let i = 0; i < cardsLeftKeys.length; i += 1) { + if (cardsLeftValues[i] >= 2) { + combinations += (rank1TotalCombinations * countTotalCombinations(cardsLeftValues[i], 2)); + } + } + } + } + + // 2 of Rank1Cards 3 of Rank2Cards + if (noOfRank1CardsHeld === 2) { + for (let i = 0; i < cardsLeftKeys.length; i += 1) { + if (cardsLeftValues[i] >= 3) { + combinations += countTotalCombinations(cardsLeftValues[i], 3); + } + } + } else if (noOfRank1CardsHeld < 2) { + if (noOfRank1CardsLeft >= (2 - noOfRank1CardsHeld)) { + const rank1TotalCombinations = countTotalCombinations(noOfRank1CardsLeft, + 2 - noOfRank1CardsHeld); + + for (let i = 0; i < cardsLeftKeys.length; i += 1) { + if (cardsLeftValues[i] >= 3) { + combinations += (rank1TotalCombinations * countTotalCombinations(cardsLeftValues[i], 3)); + } + } + } + } + } + + result.combinations = combinations; + + return result; +}; + +/** + * + * @returns {Number} number of flush combinations that can be achieved with cards being held + */ +const checkFlushCombinations = () => { + let combinations = 0; + const flushHand = {}; + + for (let i = 0; i < stats.hand.length; i += 1) { + if (stats.hand[i].hold === true) { + if (flushHand[stats.hand[i].suit] === undefined) { + flushHand[stats.hand[i].suit] = 1; + } else { + flushHand[stats.hand[i].suit] += 1; + } + } + } + + const cardsLeftValues = Object.values(cardsLeft); + + if (Object.keys(flushHand).length > 1) { + combinations = 0; + } else { + const suit = Object.keys(flushHand)[0]; + const cardsHeld = Object.values(flushHand)[0]; + + let cardsLeftWithSuit = 0; + + for (let i = 0; i < cardsLeftValues.length; i += 1) { + cardsLeftWithSuit += cardsLeftValues[i][suit]; + } + + combinations = countTotalCombinations(cardsLeftWithSuit, 5 - cardsHeld); + } + + return combinations; +}; + +/** + * + * @returns {Number} number of straight combinations that can be achieved with cards being held + */ +const checkStraightCombinations = () => { + const withinStraightResult = isHeldCardsWithinStraight(stats.hand); + + let combinations = 0; + + if (withinStraightResult.result) { + const { straightHand } = withinStraightResult; + const { diff } = withinStraightResult; + + const rankArray = Object.keys(straightHand); + + if (diff > 4) { + combinations = 0; + } else if (diff === 4) { + const firstRank = parseInt(rankArray[0], 10); + + combinations = 1; + + for (let i = 1; i < 5; i += 1) { + if (rankArray.indexOf((firstRank + i).toString()) === -1) { + // current rank is not in held cards + // find in cardsLeft + + const cardsLeftWithRank = getCardsLeftWithRank(firstRank + i); + + if (cardsLeftWithRank > 0) { + combinations *= countTotalCombinations(cardsLeftWithRank, 1); + } else { + combinations = 0; + } + } + } + } else if (diff === 3) { + let tempCombinations = 1; + + const firstRank = parseInt(rankArray[0], 10); + const lastRank = firstRank + 4; + + for (let i = firstRank; i <= lastRank; i += 1) { + if ((rankArray.indexOf((i).toString()) === -1) && (i < 15)) { + const cardsLeftWithRank = getCardsLeftWithRank(i); + + if (cardsLeftWithRank > 0) { + tempCombinations *= countTotalCombinations(cardsLeftWithRank, 1); + } else { + tempCombinations = 0; + } + } + } + + combinations += tempCombinations; + + tempCombinations = 1; + + const firstRank1 = parseInt(rankArray[0], 10) - 1; + if (firstRank1 > 0) { + const lastRank1 = firstRank1 + 4; + + for (let i = firstRank1; i <= lastRank1; i += 1) { + if ((rankArray.indexOf((i).toString()) === -1) && (i < 15)) { + const cardsLeftWithRank = getCardsLeftWithRank(i); + + if (cardsLeftWithRank > 0) { + tempCombinations *= countTotalCombinations(cardsLeftWithRank, 1); + } else { + tempCombinations = 0; + } + } + } + + combinations += tempCombinations; + } + } else if (diff === 2) { + let tempCombinations = 1; + + const firstRank = parseInt(rankArray[0], 10); + const lastRank = firstRank + 4; + + for (let i = firstRank; i <= lastRank; i += 1) { + if ((rankArray.indexOf((i).toString()) === -1) && (i < 15)) { + const cardsLeftWithRank = getCardsLeftWithRank(i); + + if (cardsLeftWithRank > 0) { + tempCombinations *= countTotalCombinations(cardsLeftWithRank, 1); + } else { + tempCombinations = 0; + } + } + } + + combinations += tempCombinations; + + tempCombinations = 1; + + const firstRank1 = parseInt(rankArray[0], 10) - 1; + if (firstRank1 > 0) { + const lastRank1 = firstRank1 + 4; + + for (let i = firstRank1; i <= lastRank1; i += 1) { + if ((rankArray.indexOf((i).toString()) === -1) && (i < 15)) { + const cardsLeftWithRank = getCardsLeftWithRank(i); + + if (cardsLeftWithRank > 0) { + tempCombinations *= countTotalCombinations(cardsLeftWithRank, 1); + } else { + tempCombinations = 0; + } + } + } + + combinations += tempCombinations; + } + + tempCombinations = 1; + + const firstRank2 = parseInt(rankArray[0], 10) - 2; + if (firstRank2 > 0) { + const lastRank2 = firstRank2 + 4; + + for (let i = firstRank2; i <= lastRank2; i += 1) { + if ((rankArray.indexOf((i).toString()) === -1) && (i < 15)) { + const cardsLeftWithRank = getCardsLeftWithRank(i); + + if (cardsLeftWithRank > 0) { + tempCombinations *= countTotalCombinations(cardsLeftWithRank, 1); + } else { + tempCombinations = 0; + } + } + } + + combinations += tempCombinations; + } + } else if (diff === 1) { + let tempCombinations = 1; + + const firstRank = parseInt(rankArray[0], 10); + const lastRank = firstRank + 4; + + for (let i = firstRank; i <= lastRank; i += 1) { + if ((rankArray.indexOf((i).toString()) === -1) && (i < 15)) { + const cardsLeftWithRank = getCardsLeftWithRank(i); + + if (cardsLeftWithRank > 0) { + tempCombinations *= countTotalCombinations(cardsLeftWithRank, 1); + } else { + tempCombinations = 0; + } + } + } + + combinations += tempCombinations; + + tempCombinations = 1; + + const firstRank1 = parseInt(rankArray[0], 10) - 1; + if (firstRank1 > 0) { + const lastRank1 = firstRank1 + 4; + + for (let i = firstRank1; i <= lastRank1; i += 1) { + if ((rankArray.indexOf((i).toString()) === -1) && (i < 15)) { + const cardsLeftWithRank = getCardsLeftWithRank(i); + + if (cardsLeftWithRank > 0) { + tempCombinations *= countTotalCombinations(cardsLeftWithRank, 1); + } else { + tempCombinations = 0; + } + } + } + + combinations += tempCombinations; + } + + tempCombinations = 1; + + const firstRank2 = parseInt(rankArray[0], 10) - 2; + if (firstRank2 > 0) { + const lastRank2 = firstRank2 + 4; + + for (let i = firstRank2; i <= lastRank2; i += 1) { + if ((rankArray.indexOf((i).toString()) === -1) && (i < 15)) { + const cardsLeftWithRank = getCardsLeftWithRank(i); + + if (cardsLeftWithRank > 0) { + tempCombinations *= countTotalCombinations(cardsLeftWithRank, 1); + } else { + tempCombinations = 0; + } + } + } + + combinations += tempCombinations; + } + + tempCombinations = 1; + + const firstRank3 = parseInt(rankArray[0], 10) - 3; + if (firstRank3 > 0) { + const lastRank3 = firstRank3 + 4; + + for (let i = firstRank3; i <= lastRank3; i += 1) { + if ((rankArray.indexOf((i).toString()) === -1) && (i < 15)) { + const cardsLeftWithRank = getCardsLeftWithRank(i); + + if (cardsLeftWithRank > 0) { + tempCombinations *= countTotalCombinations(cardsLeftWithRank, 1); + } else { + tempCombinations = 0; + } + } + } + + combinations += tempCombinations; + } + } else if (diff === 0) { + let tempCombinations = 1; + + const firstRank = parseInt(rankArray[0], 10); + const lastRank = firstRank + 4; + + for (let i = firstRank; i <= lastRank; i += 1) { + if ((rankArray.indexOf((i).toString()) === -1) && (i < 15)) { + const cardsLeftWithRank = getCardsLeftWithRank(i); + + if (cardsLeftWithRank > 0) { + tempCombinations *= countTotalCombinations(cardsLeftWithRank, 1); + } else { + tempCombinations = 0; + } + } + } + + combinations += tempCombinations; + + tempCombinations = 1; + + const firstRank1 = parseInt(rankArray[0], 10) - 1; + if (firstRank1 > 0) { + const lastRank1 = firstRank1 + 4; + + for (let i = firstRank1; i <= lastRank1; i += 1) { + if ((rankArray.indexOf((i).toString()) === -1) && (i < 15)) { + const cardsLeftWithRank = getCardsLeftWithRank(i); + + if (cardsLeftWithRank > 0) { + tempCombinations *= countTotalCombinations(cardsLeftWithRank, 1); + } else { + tempCombinations = 0; + } + } + } + + combinations += tempCombinations; + } + + tempCombinations = 1; + + const firstRank2 = parseInt(rankArray[0], 10) - 2; + if (firstRank2 > 0) { + const lastRank2 = firstRank2 + 4; + + for (let i = firstRank2; i <= lastRank2; i += 1) { + if ((rankArray.indexOf((i).toString()) === -1) && (i < 15)) { + const cardsLeftWithRank = getCardsLeftWithRank(i); + + if (cardsLeftWithRank > 0) { + tempCombinations *= countTotalCombinations(cardsLeftWithRank, 1); + } else { + tempCombinations = 0; + } + } + } + + combinations += tempCombinations; + } + + tempCombinations = 1; + + const firstRank3 = parseInt(rankArray[0], 10) - 3; + if (firstRank3 > 0) { + const lastRank3 = firstRank3 + 4; + + for (let i = firstRank3; i <= lastRank3; i += 1) { + if ((rankArray.indexOf((i).toString()) === -1) && (i < 15)) { + const cardsLeftWithRank = getCardsLeftWithRank(i); + + if (cardsLeftWithRank > 0) { + tempCombinations *= countTotalCombinations(cardsLeftWithRank, 1); + } else { + tempCombinations = 0; + } + } + } + + combinations += tempCombinations; + } + + tempCombinations = 1; + + const firstRank4 = parseInt(rankArray[0], 10) - 3; + if (firstRank4 > 0) { + const lastRank4 = firstRank4 + 4; + + for (let i = firstRank4; i <= lastRank4; i += 1) { + if ((rankArray.indexOf((i).toString()) === -1) && (i < 15)) { + const cardsLeftWithRank = getCardsLeftWithRank(i); + + if (cardsLeftWithRank > 0) { + tempCombinations *= countTotalCombinations(cardsLeftWithRank, 1); + } else { + tempCombinations = 0; + } + } + } + + combinations += tempCombinations; + } + } + } + + return combinations; +}; diff --git a/scripts/checkHand.js b/scripts/checkHand.js new file mode 100644 index 00000000..493b176d --- /dev/null +++ b/scripts/checkHand.js @@ -0,0 +1,302 @@ +/** + * + * @param {Object} stats object containing the current hand with number of suits and number of ranks + * @returns {Boolean} true if current hand is four of a kind + */ +const checkFourOfAKindHand = (input) => { + const nameCount = Object.values(input.name); + + if (nameCount.indexOf(4) !== -1) { + return true; + } + + return false; +}; + +/** + * + * @param {Object} stats object containing the current hand with number of suits and number of ranks + * @returns {Boolean} true if current hand is full house + */ +const checkFullHouseHand = (input) => { + const nameCount = Object.values(input.name); + + if (nameCount.indexOf(3) !== -1 && nameCount.indexOf(2) !== -1) { + return true; + } + + return false; +}; + +/** + * + * @param {Object} stats object containing the current hand with number of suits and number of ranks + * @returns {Boolean} true if current hand is flush + */ +const checkFlushHand = (input) => { + const suitCount = Object.values(input.suit); + + if (suitCount.indexOf(5) !== -1) { + return true; + } + + return false; +}; + +/** + * + * @param {Object} stats object containing the current hand with number of suits and number of ranks + * @returns {Boolean} true if current hand is straight + */ +const checkStraightHand = (input) => { + const nameCount = Object.values(input.name); + + // check whether there is any names repeated twice or more + for (let i = 0; i < nameCount.length; i += 1) { + if (nameCount[i] >= 2) { + return null; + } + } + + // put all ranks into a table + // if there is an ace, put both rank 1 and 14 + const rankTable = []; + let rankTable2 = null; + + if (input.name.ace === 1) { + rankTable2 = []; + } + + for (let i = 0; i < input.hand.length; i += 1) { + rankTable.push(input.hand[i].rank); + if (rankTable2 !== null) { + if (input.hand[i].name === 'ace') { + rankTable2.push(14); + } else { + rankTable2.push(input.hand[i].rank); + } + } + } + + // check rankTable to see whether sequential + rankTable.sort((a, b) => a - b); + let sequential = true; + for (let i = 1; i < rankTable.length; i += 1) { + if (rankTable[i] - 1 === rankTable[i - 1]) { + sequential = true; + } else { + sequential = false; + break; + } + } + + if (rankTable2 !== null && sequential === false) { + rankTable2.sort((a, b) => a - b); + + for (let i = 1; i < rankTable2.length; i += 1) { + if (rankTable2[i] - 1 === rankTable2[i - 1]) { + sequential = true; + } else { + sequential = false; + break; + } + } + } + + return sequential; +}; + +/** + * + * @param {Object} stats object containing the current hand with number of suits and number of ranks + * @returns {Boolean} true if current hand is three of a kind + */ +const checkThreeOfAKindHand = (input) => { + const nameCount = Object.values(input.name); + + if (nameCount.indexOf(3) !== -1) { + return true; + } + + return false; +}; + +/** + * + * @param {Object} stats object containing the current hand with number of suits and number of ranks + * @returns {Boolean} true if current hand is two pair + */ +const checkTwoPairHand = (input) => { + let noOfPairs = 0; + + const nameCount = Object.values(input.name); + + for (let i = 0; i < nameCount.length; i += 1) { + if (nameCount[i] >= 2) { + noOfPairs += 1; + } + } + + if (noOfPairs === 2) { + return true; + } + + return false; +}; + +/** + * + * @param {Object} stats object containing the current hand with number of suits and number of ranks + * @returns {Boolean} true if current hand is straight flush + */ +const checkStraightFlushHand = (input) => { + if (checkStraightHand(input) && checkFlushHand(input)) { + return true; + } + + return false; +}; + +/** + * + * @param {Object} stats object containing the current hand with number of suits and number of ranks + * @returns {Boolean} true if current hand is royal flush + */ +const checkRoyalFlushHand = (input) => { + if (checkFlushHand(input) && input.name.ace === 1 && input.name.king === 1 && input.name.queen === 1 && input.name.jack === 1 && input.name['10'] === 1) { + return true; + } + + return false; +}; + +/** + * + * @param {Object} stats.hand object containing the current hand + * @returns {Boolean} true if current hand contains cards of the same suit + */ +const isHeldCardsSameSuit = (statsHand) => { + const result = { + suit: '', + result: false, + }; + + let suitPlaceholder = ''; + for (let i = 0; i < statsHand.length; i += 1) { + if (statsHand[i].hold === true) { + if (suitPlaceholder === '') { + suitPlaceholder = statsHand[i].suit; + } else if (statsHand[i].suit !== suitPlaceholder) { + return result; + } + } + } + + result.suit = suitPlaceholder; + result.result = true; + + return result; +}; + +/** + * + * @param {Object} stats.hand object containing the current hand + * @returns {Boolean} true if current hand contains cards of the same rank + */ +const isHeldCardsSameName = (statsHand) => { + let cardsAreSameName = true; + let namePlaceholder = ''; + for (let i = 0; i < statsHand.length; i += 1) { + if (statsHand[i].hold === true) { + if (namePlaceholder === '') { + namePlaceholder = statsHand[i].name; + } else if (statsHand[i].name !== namePlaceholder) { + cardsAreSameName = false; + return cardsAreSameName; + } + } + } + + return cardsAreSameName; +}; + +/** + * + * @param {Object} stats.hand object containing the current hand + * @returns {Boolean} true if current hand contains cards from the royal flush group + */ +const isHeldCardsRoyal = (statsHand) => { + const result = { + royalHand: {}, + result: false, + }; + + const royalHand = { + ace: 0, + king: 0, + queen: 0, + jack: 0, + 10: 0, + }; + + // if held cards do not contain royal cards, return false + for (let i = 0; i < statsHand.length; i += 1) { + if (statsHand[i].hold === true) { + if (royalHand[statsHand[i].name] === undefined) { + result.result = false; + return result; + } + royalHand[statsHand[i].name] += 1; + } + } + + if (royalHand.ace > 1 + || royalHand.king > 1 + || royalHand.queen > 1 + || royalHand.jack > 1 + || royalHand[10] > 1) { + result.result = false; + + return result; + } + + result.royalHand = royalHand; + result.result = true; + return result; +}; + +/** + * + * @param {Object} stats.hand object containing the current hand + * @returns {Boolean} true if lowest rank and highest rank of cards being held are within 5 of each other + */ +const isHeldCardsWithinStraight = (statsHand) => { + const result = { + straightHand: {}, + diff: 0, + result: false, + }; + + // if there is more than 2 cards of the same rank, it is not within straight result + for (let i = 0; i < statsHand.length; i += 1) { + if (statsHand[i].hold === true) { + if (result.straightHand[statsHand[i].rank] === undefined) { + result.straightHand[statsHand[i].rank] = 1; + } else { + return result; + } + } + } + + // if there is not more than 1 card per rank, check if the lowest rank and highest rank are within 5 of each other + const rankArray = Object.keys(result.straightHand); + const diff = parseInt(rankArray[rankArray.length - 1], 10) - parseInt(rankArray[0], 10); + if (diff <= 4) { + result.result = true; + result.diff = diff; + return result; + } + + result.straightHand = {}; + return result; +}; diff --git a/scripts/functionHelper.js b/scripts/functionHelper.js new file mode 100644 index 00000000..d59dbbaa --- /dev/null +++ b/scripts/functionHelper.js @@ -0,0 +1,140 @@ +/** + * + * @param {Object} object of objects with keys from 'ace' to 'king' containing the number of cards still in the deck + * @returns {Array} array of stats objects + */ +const convertCardsLeftToStats = (cardsLeft) => { + const cardsLeftKeys = Object.keys(cardsLeft); + const cardsLeftValues = Object.values(cardsLeft); + + const cleanedUpCardsLeft = []; + + for (let i = 0; i < cardsLeftKeys.length; i += 1) { + const cardsLeftValues2 = Object.values(cardsLeftValues[i]); + for (let j = 0; j < cardsLeftValues2.length; j += 1) { + if (cardsLeftValues2[j] !== 0) { + const cleanedUpCardsLeftItem = {}; + cleanedUpCardsLeftItem.name = cardsLeftKeys[i]; + + if (j === 0) { + cleanedUpCardsLeftItem.suit = 'clubs'; + } else if (j === 1) { + cleanedUpCardsLeftItem.suit = 'spades'; + } else if (j === 2) { + cleanedUpCardsLeftItem.suit = 'hearts'; + } else { + cleanedUpCardsLeftItem.suit = 'diamonds'; + } + + if (cardsLeftKeys[i] === 'jack') { + cleanedUpCardsLeftItem.rank = 11; + } else if (cardsLeftKeys[i] === 'queen') { + cleanedUpCardsLeftItem.rank = 12; + } else if (cardsLeftKeys[i] === 'king') { + cleanedUpCardsLeftItem.rank = 13; + } else if (cardsLeftKeys[i] === 'ace') { + cleanedUpCardsLeftItem.rank = 14; + } else { + cleanedUpCardsLeftItem.rank = parseInt(cardsLeftKeys[i], 10); + } + cleanedUpCardsLeft.push(cleanedUpCardsLeftItem); + } + } + } + + return cleanedUpCardsLeft; +}; + +/** + * + * @returns {Number} number of cards that are being held by the player and will not be replaced with fresh cards + */ +const countHeldCards = () => { + let counter = 0; + + for (let i = 0; i < stats.hand.length; i += 1) { + if (stats.hand[i].hold === true) { + counter += 1; + } + } + + return counter; +}; + +/** + * + * @returns {Number} number of cards that are to be replaced with fresh cards + */ +const countReplacedCards = () => { + let replaceCounter = 0; + for (let i = 0; i < stats.hand.length; i += 1) { + if (stats.hand[i].hold === false) { + replaceCounter += 1; + } + } + + return replaceCounter; +}; + +/** + * + * @returns {Array} newDeck array contains a fresh deck of 52 cards + */ +const makeDeck = () => { + const newDeck = []; + const suits = ['hearts', 'diamonds', 'clubs', 'spades']; + const colors = ['red', 'red', 'black', 'black']; + + for (let suitIndex = 0; suitIndex < suits.length; suitIndex += 1) { + const currentSuit = suits[suitIndex]; + const color = colors[suitIndex]; + + for (let rankCounter = 2; rankCounter <= 14; rankCounter += 1) { + let cardName = `${rankCounter}`; + + if (cardName === '14') { + cardName = 'ace'; + } else if (cardName === '11') { + cardName = 'jack'; + } else if (cardName === '12') { + cardName = 'queen'; + } else if (cardName === '13') { + cardName = 'king'; + } + + const card = { + name: cardName, + suit: currentSuit, + rank: rankCounter, + pic: `./images/cards/${cardName}_of_${currentSuit}.png`, + color, + }; + + newDeck.push(card); + } + } + + return newDeck; +}; + +/** + * + * @param {Array} cards containing 52 newly created cards + * @returns {Array} 52 shuffled cards + */ +const shuffleCards = (cards) => { + // Loop over the card deck array once + for (let currentIndex = 0; currentIndex < cards.length; currentIndex += 1) { + // Select a random index in the deck + const randomIndex = Math.floor(Math.random() * cards.length); + // Select the card that corresponds to randomIndex + const randomCard = cards[randomIndex]; + // Select the card that corresponds to currentIndex + const currentCard = cards[currentIndex]; + // Swap positions of randomCard and currentCard in the deck + cards[currentIndex] = randomCard; + cards[randomIndex] = currentCard; + } + // Return the shuffled deck + return cards; +}; diff --git a/scripts/main.js b/scripts/main.js new file mode 100644 index 00000000..30442aa1 --- /dev/null +++ b/scripts/main.js @@ -0,0 +1,634 @@ +/* eslint-disable no-undef */ +let stats = { + hand: [], + suit: { + clubs: 0, + spades: 0, + hearts: 0, + diamonds: 0, + }, + name: { + ace: 0, + 2: 0, + 3: 0, + 4: 0, + 5: 0, + 6: 0, + 7: 0, + 8: 0, + 9: 0, + 10: 0, + jack: 0, + queen: 0, + king: 0, + }, +}; +const rewards = { + royalFlush: 250, + straightFlush: 50, + fourOfAKind: 25, + fullHouse: 9, + flush: 6, + straight: 4, + threeOfAKind: 3, + twoPairs: 2, + jacksOrBetter: 1, +}; +const probability = { + royalFlush: 0, + straightFlush: 0, + fourOfAKind: 0, + fullHouse: 0, + flush: 0, + straight: 0, + threeOfAKind: 0, + twoPairs: 0, + jacksOrBetter: 0, +}; +let cardsLeft = { + ace: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 2: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 3: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 4: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 5: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 6: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 7: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 8: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 9: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 10: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + jack: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + queen: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + king: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, +}; +let shuffledDeck = []; +let playerCredits = 100; +let playerBet = 0; +let mode = ''; +let outcome = 'Sorry you lost.'; +let foundHand = ''; +let totalCombinationsAvailable = 0; + + +/** + * + * @param {String|Number} string or number representing the rank + * @returns {Number} number of cards left with the rank + */ +const getCardsLeftWithRank = (i) => { + let rank = i; + + if (typeof (rank) === 'string') { + if (rank === 'king') { + rank = Object.values(cardsLeft.king).reduce((a, b) => a + b, 0); + return rank; + } if (rank === 'queen') { + rank = Object.values(cardsLeft.queen).reduce((a, b) => a + b, 0); + return rank; + } if (rank === 'jack') { + rank = Object.values(cardsLeft.jack).reduce((a, b) => a + b, 0); + return rank; + } if (rank === 'ace') { + rank = Object.values(cardsLeft.ace).reduce((a, b) => a + b, 0); + return rank; + } + rank = parseInt(rank, 10); + } + + if (rank === 1) { + rank = Object.values(cardsLeft.ace).reduce((a, b) => a + b, 0); + } else if (rank === 11) { + rank = Object.values(cardsLeft.jack).reduce((a, b) => a + b, 0); + } else if (rank === 12) { + rank = Object.values(cardsLeft.queen).reduce((a, b) => a + b, 0); + } else if (rank === 13) { + rank = Object.values(cardsLeft.king).reduce((a, b) => a + b, 0); + } else if (rank === 14) { + rank = Object.values(cardsLeft.ace).reduce((a, b) => a + b, 0); + } else { + rank = Object.values(cardsLeft[rank]).reduce((a, b) => a + b, 0); + } + + return rank; +}; + +/** + * + * run through the current hand of cards through all winning combinations starting with royal flush down to two pairs + * if we find any winning combination, solution will not search for other winning outcomes + */ +const calcHandScore = () => { + if (checkRoyalFlushHand(stats)) { + outcome = 'Royal flush found!'; + foundHand = 'royalFlush'; + return; + } + if (checkStraightFlushHand(stats)) { + outcome = 'Straight flush found!'; + foundHand = 'straightFlush'; + return; + } + if (checkFourOfAKindHand(stats)) { + outcome = 'Four of a kind found!'; + foundHand = 'fourOfAKind'; + return; + } + if (checkFullHouseHand(stats)) { + outcome = 'Full house found!'; + foundHand = 'fullHouse'; + return; + } + if (checkFlushHand(stats)) { + outcome = 'Flush found!'; + foundHand = 'flush'; + return; + } + if (checkStraightHand(stats)) { + outcome = 'Straight found!'; + foundHand = 'straight'; + return; + } + if (checkThreeOfAKindHand(stats)) { + outcome = 'Three of a kind found!'; + foundHand = 'threeOfAKind'; + return; + } + if (checkTwoPairHand(stats)) { + outcome = 'Two pairs found!'; + foundHand = 'twoPairs'; + } +}; + +/** + * + * count the number of credits that player has won if they get a winning hand + */ +const countPlayerCredits = () => { + if (outcome === 'Royal flush found!' && playerBet === 5) { + playerCredits += 4000; + } else if (outcome !== 'Sorry you lost.') { + playerCredits += (playerBet * rewards[foundHand]); + } + + // if after tallying, player still has zero, game over + if (playerCredits === 0) { + gameOver(); + } else { + + } +}; + +/** + * + * resets game, updates instructions + */ +const resetGame = () => { + playerBet = 0; + mode = ''; + + // clear stats + stats.hand = []; + stats.suit = { + clubs: 0, + spades: 0, + hearts: 0, + diamonds: 0, + }; + stats.name = { + ace: 0, + 2: 0, + 3: 0, + 4: 0, + 5: 0, + 6: 0, + 7: 0, + 8: 0, + 9: 0, + 10: 0, + jack: 0, + queen: 0, + king: 0, + }; + + document.getElementById('cards').className = 'display-none'; + document.getElementById('probabilities').className = 'display-none'; + shuffledDeck = shuffleCards(makeDeck()); + outcome = 'Sorry you lost.'; +}; + +/** + * + * replace the cards that are not held in current hand with new cards from the deck + */ +const refreshHand = () => { + let drawnCard; + + for (let i = 4; i >= 0; i -= 1) { + if (stats.hand[i] !== undefined && stats.hand[i].hold === false) { + // remove cards i do not want to hold first + stats.name[stats.hand[i].name] -= 1; + stats.suit[stats.hand[i].suit] -= 1; + + drawnCard = shuffledDeck.pop(); + drawnCard.hold = false; + + // replace cards i do not want with new cards + stats.hand.splice(i, 1, drawnCard); + + stats.name[drawnCard.name] += 1; + stats.suit[drawnCard.suit] += 1; + + cardsLeft[drawnCard.name][drawnCard.suit] -= 1; + } + } +}; + +/** + * + * @param {Array} array of stats objects that represent the cards that are left and yet to be drawn + * @returns {Array} array of different combination stats objects that can be built via 5 cards + */ +const buildStats = (cleanedUpCardsLeft) => { + const statsList = []; + + for (let i = 0; i < cleanedUpCardsLeft.length; i += 1) { + for (let j = i + 1; j < cleanedUpCardsLeft.length; j += 1) { + for (let k = j + 1; k < cleanedUpCardsLeft.length; k += 1) { + for (let l = k + 1; l < cleanedUpCardsLeft.length; l += 1) { + for (let m = l + 1; m < cleanedUpCardsLeft.length; m += 1) { + const stats = {}; + stats.hand = []; + stats.name = { + 2: 0, + 3: 0, + 4: 0, + 5: 0, + 6: 0, + 7: 0, + 8: 0, + 9: 0, + 10: 0, + ace: 0, + jack: 0, + king: 0, + queen: 0, + }; + stats.suit = { + clubs: 0, + spades: 0, + hearts: 0, + diamonds: 0, + }; + + stats.name[cleanedUpCardsLeft[i].name] += 1; + stats.name[cleanedUpCardsLeft[j].name] += 1; + stats.name[cleanedUpCardsLeft[k].name] += 1; + stats.name[cleanedUpCardsLeft[l].name] += 1; + stats.name[cleanedUpCardsLeft[m].name] += 1; + + stats.suit[cleanedUpCardsLeft[i].suit] += 1; + stats.suit[cleanedUpCardsLeft[j].suit] += 1; + stats.suit[cleanedUpCardsLeft[k].suit] += 1; + stats.suit[cleanedUpCardsLeft[l].suit] += 1; + stats.suit[cleanedUpCardsLeft[m].suit] += 1; + + stats.hand.push(cleanedUpCardsLeft[i]); + stats.hand.push(cleanedUpCardsLeft[j]); + stats.hand.push(cleanedUpCardsLeft[k]); + stats.hand.push(cleanedUpCardsLeft[l]); + stats.hand.push(cleanedUpCardsLeft[m]); + + statsList.push(stats); + } + } + } + } + } + + return statsList; +}; + +/** + * + * @param {Array} array of stats objects containing the current hand with number of suits and number of ranks + * @returns {Object} object containing probabilities for each winning hand based on statsList + */ +const runStatsAgainstOutcomes = (statsList) => { + const statOutcome = { + royalFlushCombinations: 0, + straightFlushCombinations: 0, + fourOfAKindCombinations: 0, + fullHouseCombinations: 0, + flushCombinations: 0, + straightCombinations: 0, + threeOfAKindCombinations: 0, + twoPairCombinations: 0, + }; + + for (let i = 0; i < statsList.length; i += 1) { + if (checkRoyalFlushHand(statsList[i])) { + statOutcome.royalFlushCombinations += 1; + } + if (checkStraightFlushHand(statsList[i])) { + statOutcome.straightFlushCombinations += 1; + } + if (checkFourOfAKindHand(statsList[i])) { + statOutcome.fourOfAKindCombinations += 1; + } + if (checkFullHouseHand(statsList[i])) { + statOutcome.fullHouseCombinations += 1; + } + if (checkFlushHand(statsList[i])) { + statOutcome.flushCombinations += 1; + } + if (checkStraightHand(statsList[i])) { + statOutcome.straightCombinations += 1; + } + if (checkThreeOfAKindHand(statsList[i])) { + statOutcome.threeOfAKindCombinations += 1; + } + if (checkTwoPairHand(statsList[i])) { + statOutcome.twoPairCombinations += 1; + } + } + + return statOutcome; +}; + +/** + * + * calculates the probability of each winning hand depending on what cards player hold or don't hold + */ +const calculateProbability = () => { + // take into account the hand and the amount + // of cards being held or to be replaced + + const cardsToBeReplaced = countReplacedCards(); + totalCombinationsAvailable = countTotalCombinations(shuffledDeck.length, cardsToBeReplaced); + updateTotalCombinationsAvailableUI(totalCombinationsAvailable); + + if (cardsToBeReplaced === 5) { + // find all combinations + const cleanedUpCardsLeft = convertCardsLeftToStats(cardsLeft); + const statsList = buildStats(cleanedUpCardsLeft); + const statOutcome = runStatsAgainstOutcomes(statsList); + + probability.royalFlush = (statOutcome.royalFlushCombinations + / totalCombinationsAvailable) * 100; + probability.straightFlush = (statOutcome.straightFlushCombinations + / totalCombinationsAvailable) * 100; + probability.fourOfAKind = (statOutcome.fourOfAKindCombinations + / totalCombinationsAvailable) * 100; + probability.fullHouse = (statOutcome.fullHouseCombinations + / totalCombinationsAvailable) * 100; + probability.flush = (statOutcome.flushCombinations + / totalCombinationsAvailable) * 100; + probability.straight = (statOutcome.straightCombinations + / totalCombinationsAvailable) * 100; + probability.threeOfAKind = (statOutcome.threeOfAKindCombinations + / totalCombinationsAvailable) * 100; + probability.twoPairs = (statOutcome.twoPairCombinations + / totalCombinationsAvailable) * 100; + + updateProbabilityUI(); + } else if (cardsToBeReplaced === 0) { + probability.royalFlush = checkRoyalFlushHand(stats) ? 100 : 0; + probability.straightFlush = checkStraightFlushHand(stats) ? 100 : 0; + probability.fourOfAKind = checkFourOfAKindHand(stats) ? 100 : 0; + probability.fullHouse = checkFullHouseHand(stats) ? 100 : 0; + probability.flush = checkFlushHand(stats) ? 100 : 0; + probability.straight = checkStraightHand(stats) ? 100 : 0; + probability.threeOfAKind = checkThreeOfAKindHand(stats) ? 100 : 0; + probability.twoPairs = checkTwoPairHand(stats) ? 100 : 0; + updateProbabilityUI(); + } else { + const royalFlushCombinations = checkRoyalFlushCombinations(); + probability.royalFlush = (royalFlushCombinations / totalCombinationsAvailable) * 100; + + const straightFlushCombinations = checkStraightFlushCombinations(); + probability.straightFlush = (straightFlushCombinations / totalCombinationsAvailable) * 100; + + const fourOfAKindCombinations = checkFourOfAKindCombinations(); + probability.fourOfAKind = fourOfAKindCombinations.alreadyWin ? 100 + : (fourOfAKindCombinations.combinations / totalCombinationsAvailable) * 100; + + const fullHouseCombinations = checkFullHouseCombinations(); + probability.fullHouse = fullHouseCombinations.alreadyWin ? 100 + : (fullHouseCombinations.combinations / totalCombinationsAvailable) * 100; + + const flushCombinations = checkFlushCombinations(); + probability.flush = (flushCombinations / totalCombinationsAvailable) * 100; + + const straightCombinations = checkStraightCombinations(); + probability.straight = (straightCombinations / totalCombinationsAvailable) * 100; + + const threeOfAKindCombinations = checkThreeOfAKindCombinations(); + probability.threeOfAKind = threeOfAKindCombinations.alreadyWin ? 100 + : (threeOfAKindCombinations.combinations / totalCombinationsAvailable) * 100; + + const twoPairCombinations = checkTwoPairCombinations(); + probability.twoPairs = twoPairCombinations.alreadyWin ? 100 + : (twoPairCombinations.combinations / totalCombinationsAvailable) * 100; + + updateProbabilityUI(); + } +}; + +/** + * + * bet 1 credit + */ +const bet1 = () => { + if (mode === 'finalDeal') { + resetGame(); + } + + if (playerBet < 5 && playerCredits !== 0) { + playerBet += 1; + playerCredits -= 1; + + if (playerBet === 5) { + disableButton('bet-1'); + } + + disableButton('bet-5'); + enableButton('deal'); + + updatePlayerBetUI(); + updatePlayerCreditsUI(); + + highlightRewardColumn(); + } +}; + +/** + * + * bet 5 credits + */ +const bet5 = () => { + if (mode === 'finalDeal') { + resetGame(); + } + + if (playerCredits >= 5) { + playerBet = 5; + playerCredits -= 5; + } else { + playerBet = playerCredits; + playerCredits = 0; + } + + disableButton('bet-5'); + disableButton('bet-1'); + enableButton('deal'); + + updatePlayerBetUI(); + updatePlayerCreditsUI(); + + highlightRewardColumn(); +}; + + +/** + * + * deal cards. depending on which stage player is at, either at first draw or second draw, update the instructions or outcomes accordingly + */ +const deal = () => { + disableButton('bet-1'); + disableButton('bet-5'); + disableButton('deal'); + + if (mode === '') { + mode = 'firstDeal'; + } else if (mode === 'firstDeal') { + mode = 'finalDeal'; + } + + if (mode === 'firstDeal') { + let drawnCard; + + enableButton('calculate-probability'); + + for (let i = 0; i < 5; i += 1) { + drawnCard = shuffledDeck.pop(); + drawnCard.hold = false; + + stats.hand.push(drawnCard); + stats.name[drawnCard.name] += 1; + stats.suit[drawnCard.suit] += 1; + + cardsLeft[drawnCard.name][drawnCard.suit] -= 1; + } + + updateCardsUI(); + updateInstructions( + "Click on any card to hold and press Deal again.", + ); + } else if (mode === 'finalDeal') { + refreshHand(); + updateCardsUI(); + calcHandScore(); + + updateInstructions(`${outcome} Restart by pressing Bet 1 or Bet 5 and pressing Deal after.`); + + countPlayerCredits(); + updatePlayerCreditsUI(); + + playerBet = 0; + + updatePlayerBetUI(); + if (playerCredits !== 0) { + enableButton('bet-1'); + enableButton('bet-5'); + } + } +}; + + +/** + * + * start the game + */ +const initGame = () => { + shuffledDeck = shuffleCards(makeDeck()); + + document.getElementById('bet-1').addEventListener('click', () => bet1()); + document.getElementById('bet-5').addEventListener('click', () => bet5()); + document.getElementById('deal').addEventListener('click', () => deal()); + document.getElementById('calculate-probability').addEventListener('click', () => calculateProbability()); +}; + + +/** + * + * game is over. update instructions + */ +const gameOver = () => { + updateInstructions('Game over.'); +}; + +initGame(); diff --git a/scripts/testHands.js b/scripts/testHands.js new file mode 100644 index 00000000..e4efd611 --- /dev/null +++ b/scripts/testHands.js @@ -0,0 +1,1513 @@ +const royalFlushHand = { + hand: [ + { + name: 'ace', + suit: 'diamonds', + rank: 1, + pic: './images/cards/ace_of_diamonds.png', + hold: false, + }, + { + name: 'king', + suit: 'diamonds', + rank: 13, + pic: './images/cards/king_of_diamonds.png', + hold: false, + }, + { + name: 'queen', + suit: 'diamonds', + rank: 12, + pic: './images/cards/queen_of_diamonds.png', + hold: false, + }, + { + name: 'jack', + suit: 'diamonds', + rank: 11, + pic: './images/cards/jack_of_diamonds.png', + hold: false, + }, + { + name: '10', + suit: 'diamonds', + rank: 10, + pic: './images/cards/10_of_diamonds.png', + hold: false, + }, + ], + suit: { + clubs: 0, + spades: 0, + hearts: 0, + diamonds: 5, + }, + name: { + 2: 0, + 3: 0, + 4: 0, + 5: 0, + 6: 0, + 7: 0, + 8: 0, + 9: 0, + 10: 1, + ace: 1, + jack: 1, + queen: 1, + king: 1, + }, +}; + +const testStraightFlushHand1 = { + hand: [ + { + name: '7', + suit: 'diamonds', + rank: 7, + pic: './images/cards/7_of_diamonds.png', + hold: false, + }, + { + name: '8', + suit: 'diamonds', + rank: 8, + pic: './images/cards/8_of_diamonds.png', + hold: false, + }, + { + name: '9', + suit: 'diamonds', + rank: 9, + pic: './images/cards/9_of_diamonds.png', + hold: false, + }, + { + name: 'jack', + suit: 'diamonds', + rank: 11, + pic: './images/cards/jack_of_diamonds.png', + hold: false, + }, + { + name: '10', + suit: 'diamonds', + rank: 10, + pic: './images/cards/10_of_diamonds.png', + hold: false, + }, + ], + suit: { + clubs: 0, + spades: 0, + hearts: 0, + diamonds: 5, + }, + name: { + 2: 0, + 3: 0, + 4: 0, + 5: 0, + 6: 0, + 7: 1, + 8: 1, + 9: 1, + 10: 1, + ace: 0, + jack: 1, + queen: 0, + king: 0, + }, +}; + +const testStraightFlushCardsLeft1 = { + ace: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 2: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 3: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 4: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 5: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 6: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 7: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 0, + }, + 8: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 0, + }, + 9: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 0, + }, + 10: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 0, + }, + jack: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 0, + }, + queen: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + king: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, +}; + +const twoPairHand = { + hand: [ + { + name: '2', + suit: 'hearts', + rank: 2, + pic: './images/cards/2_of_hearts.png', + hold: false, + }, + { + name: '4', + suit: 'hearts', + rank: 4, + pic: './images/cards/4_of_hearts.png', + hold: false, + }, + { + name: '2', + suit: 'spades', + rank: 2, + pic: './images/cards/2_of_spades.png', + hold: false, + }, + { + name: '4', + suit: 'clubs', + rank: 4, + pic: './images/cards/4_of_clubs.png', + hold: false, + }, + { + name: 'ace', + suit: 'hearts', + rank: 1, + pic: './images/cards/ace_of_hearts.png', + hold: false, + }, + ], + suit: { + clubs: 1, + spades: 1, + hearts: 3, + diamonds: 0, + }, + name: { + 2: 2, + 3: 0, + 4: 2, + 5: 0, + 6: 0, + 7: 0, + 8: 0, + 9: 0, + 10: 0, + ace: 1, + jack: 0, + queen: 0, + king: 0, + }, +}; + +const twoPairCardsLeft = { + ace: { + clubs: 1, + spades: 1, + hearts: 0, + diamonds: 1, + }, + 2: { + clubs: 1, + spades: 0, + hearts: 0, + diamonds: 1, + }, + 3: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 4: { + clubs: 0, + spades: 1, + hearts: 0, + diamonds: 1, + }, + 5: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 6: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 7: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 8: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 9: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 10: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + jack: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + queen: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + king: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, +}; + +const fullHouseHand = { + hand: [ + { + name: '2', + suit: 'hearts', + rank: 2, + pic: './images/cards/2_of_hearts.png', + hold: false, + }, + { + name: '2', + suit: 'diamonds', + rank: 2, + pic: './images/cards/2_of_diamonds.png', + hold: false, + }, + { + name: '2', + suit: 'spades', + rank: 2, + pic: './images/cards/2_of_spades.png', + hold: false, + }, + { + name: '4', + suit: 'clubs', + rank: 4, + pic: './images/cards/4_of_clubs.png', + hold: false, + }, + { + name: '4', + suit: 'hearts', + rank: 4, + pic: './images/cards/4_of_hearts.png', + hold: false, + }, + ], + suit: { + clubs: 1, + spades: 1, + hearts: 2, + diamonds: 1, + }, + name: { + 2: 3, + 3: 0, + 4: 2, + 5: 0, + 6: 0, + 7: 0, + 8: 0, + 9: 0, + 10: 0, + ace: 0, + jack: 0, + queen: 0, + king: 0, + }, +}; + +const testFullHouseHand = { + hand: [ + { + name: '2', + suit: 'hearts', + rank: 2, + pic: './images/cards/2_of_hearts.png', + hold: false, + }, + { + name: '2', + suit: 'diamonds', + rank: 2, + pic: './images/cards/2_of_diamonds.png', + hold: false, + }, + { + name: '2', + suit: 'spades', + rank: 2, + pic: './images/cards/2_of_spades.png', + hold: false, + }, + { + name: '4', + suit: 'clubs', + rank: 4, + pic: './images/cards/4_of_clubs.png', + hold: false, + }, + { + name: '4', + suit: 'hearts', + rank: 4, + pic: './images/cards/4_of_hearts.png', + hold: false, + }, + ], + suit: { + clubs: 1, + spades: 1, + hearts: 2, + diamonds: 1, + }, + name: { + 2: 3, + 3: 0, + 4: 2, + 5: 0, + 6: 0, + 7: 0, + 8: 0, + 9: 0, + 10: 0, + ace: 0, + jack: 0, + queen: 0, + king: 0, + }, +}; + +const testFullHouseCardsLeft = { + ace: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 2: { + clubs: 1, + spades: 0, + hearts: 0, + diamonds: 0, + }, + 3: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 4: { + clubs: 0, + spades: 1, + hearts: 0, + diamonds: 1, + }, + 5: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 6: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 7: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 8: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 9: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 10: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + jack: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + queen: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + king: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, +}; + +const testFourOfAKindHand = { + hand: [ + { + name: '2', + suit: 'hearts', + rank: 2, + pic: './images/cards/2_of_hearts.png', + hold: false, + }, + { + name: '2', + suit: 'diamonds', + rank: 2, + pic: './images/cards/2_of_diamonds.png', + hold: false, + }, + { + name: '2', + suit: 'spades', + rank: 2, + pic: './images/cards/2_of_spades.png', + hold: false, + }, + { + name: '3', + suit: 'clubs', + rank: 3, + pic: './images/cards/3_of_clubs.png', + hold: false, + }, + { + name: '6', + suit: 'hearts', + rank: 6, + pic: './images/cards/6_of_hearts.png', + hold: false, + }, + ], + suit: { + clubs: 1, + spades: 1, + hearts: 2, + diamonds: 1, + }, + name: { + 2: 3, + 3: 1, + 4: 0, + 5: 0, + 6: 1, + 7: 0, + 8: 0, + 9: 0, + 10: 0, + ace: 0, + jack: 0, + queen: 0, + king: 0, + }, +}; + +const testFourOfAKindCardsLeft = { + ace: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 2: { + clubs: 1, + spades: 0, + hearts: 0, + diamonds: 0, + }, + 3: { + clubs: 0, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 4: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 5: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 6: { + clubs: 1, + spades: 1, + hearts: 0, + diamonds: 1, + }, + 7: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 8: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 9: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 10: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + jack: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + queen: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + king: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, +}; + +const threeOfAKindHand = { + hand: [ + { + name: '2', + suit: 'hearts', + rank: 2, + pic: './images/cards/2_of_hearts.png', + hold: false, + }, + { + name: '2', + suit: 'diamonds', + rank: 2, + pic: './images/cards/2_of_diamonds.png', + hold: false, + }, + { + name: '2', + suit: 'spades', + rank: 2, + pic: './images/cards/2_of_spades.png', + hold: false, + }, + { + name: '4', + suit: 'clubs', + rank: 4, + pic: './images/cards/4_of_clubs.png', + hold: false, + }, + { + name: '6', + suit: 'hearts', + rank: 6, + pic: './images/cards/6_of_hearts.png', + hold: false, + }, + ], + suit: { + clubs: 1, + spades: 1, + hearts: 2, + diamonds: 1, + }, + name: { + 2: 3, + 3: 0, + 4: 1, + 5: 0, + 6: 1, + 7: 0, + 8: 0, + 9: 0, + 10: 0, + ace: 0, + jack: 0, + queen: 0, + king: 0, + }, +}; + +const threeOfAKindCardsLeft = { + ace: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 2: { + clubs: 1, + spades: 0, + hearts: 0, + diamonds: 0, + }, + 3: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 4: { + clubs: 0, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 5: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 6: { + clubs: 1, + spades: 1, + hearts: 0, + diamonds: 1, + }, + 7: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 8: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 9: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 10: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + jack: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + queen: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + king: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, +}; + +/** + * 2 3 4 5 6 + */ +const straightHand1 = { + hand: [ + { + name: '2', + suit: 'hearts', + rank: 2, + pic: './images/cards/2_of_hearts.png', + hold: false, + }, + { + name: '3', + suit: 'diamonds', + rank: 3, + pic: './images/cards/3_of_diamonds.png', + hold: false, + }, + { + name: '4', + suit: 'spades', + rank: 4, + pic: './images/cards/4_of_spades.png', + hold: false, + }, + { + name: '5', + suit: 'clubs', + rank: 5, + pic: './images/cards/5_of_clubs.png', + hold: false, + }, + { + name: '6', + suit: 'hearts', + rank: 6, + pic: './images/cards/6_of_hearts.png', + hold: false, + }, + ], + suit: { + clubs: 1, + spades: 1, + hearts: 2, + diamonds: 1, + }, + name: { + 2: 1, + 3: 1, + 4: 1, + 5: 1, + 6: 1, + 7: 0, + 8: 0, + 9: 0, + 10: 0, + ace: 0, + jack: 0, + queen: 0, + king: 0, + }, +}; + +const straightHand1CardsLeft = { + ace: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 2: { + clubs: 1, + spades: 1, + hearts: 0, + diamonds: 1, + }, + 3: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 0, + }, + 4: { + clubs: 1, + spades: 0, + hearts: 1, + diamonds: 1, + }, + 5: { + clubs: 0, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 6: { + clubs: 1, + spades: 1, + hearts: 0, + diamonds: 1, + }, + 7: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 8: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 9: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 10: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + jack: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + queen: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + king: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, +}; + +/** + * A 2 3 4 5 + */ +const straightHand2 = { + hand: [ + { + name: 'ace', + suit: 'hearts', + rank: 1, + pic: './images/cards/ace_of_hearts.png', + hold: false, + }, + { + name: '3', + suit: 'diamonds', + rank: 3, + pic: './images/cards/3_of_diamonds.png', + hold: false, + }, + { + name: '4', + suit: 'spades', + rank: 4, + pic: './images/cards/4_of_spades.png', + hold: false, + }, + { + name: '5', + suit: 'clubs', + rank: 5, + pic: './images/cards/5_of_clubs.png', + hold: false, + }, + { + name: '2', + suit: 'hearts', + rank: 2, + pic: './images/cards/2_of_hearts.png', + hold: false, + }, + ], + suit: { + clubs: 1, + spades: 1, + hearts: 2, + diamonds: 1, + }, + name: { + 2: 1, + 3: 1, + 4: 1, + 5: 1, + 6: 0, + 7: 0, + 8: 0, + 9: 0, + 10: 0, + ace: 1, + jack: 0, + queen: 0, + king: 0, + }, +}; + +const straightHand2CardsLeft = { + ace: { + clubs: 1, + spades: 1, + hearts: 0, + diamonds: 1, + }, + 2: { + clubs: 1, + spades: 1, + hearts: 0, + diamonds: 1, + }, + 3: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 0, + }, + 4: { + clubs: 1, + spades: 0, + hearts: 1, + diamonds: 1, + }, + 5: { + clubs: 0, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 6: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 7: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 8: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 9: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 10: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + jack: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + queen: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + king: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, +}; + +/** + * 7 8 9 10 11 + */ +const straightHand3 = { + hand: [ + { + name: '7', + suit: 'hearts', + rank: 7, + pic: './images/cards/7_of_hearts.png', + hold: false, + }, + { + name: '8', + suit: 'diamonds', + rank: 8, + pic: './images/cards/8_of_diamonds.png', + hold: false, + }, + { + name: '9', + suit: 'spades', + rank: 9, + pic: './images/cards/9_of_spades.png', + hold: false, + }, + { + name: '10', + suit: 'clubs', + rank: 10, + pic: './images/cards/10_of_clubs.png', + hold: false, + }, + { + name: 'jack', + suit: 'hearts', + rank: 11, + pic: './images/cards/jack_of_hearts.png', + hold: false, + }, + ], + suit: { + clubs: 1, + spades: 1, + hearts: 2, + diamonds: 1, + }, + name: { + 2: 0, + 3: 0, + 4: 0, + 5: 0, + 6: 0, + 7: 1, + 8: 1, + 9: 1, + 10: 1, + ace: 0, + jack: 1, + queen: 0, + king: 0, + }, +}; + +/** + * 10 J Q K A + */ +const straightHand4 = { + hand: [ + { + name: 'ace', + suit: 'hearts', + rank: 1, + pic: './images/cards/ace_of_hearts.png', + hold: false, + }, + { + name: 'king', + suit: 'diamonds', + rank: 13, + pic: './images/cards/king_of_diamonds.png', + hold: false, + }, + { + name: 'queen', + suit: 'spades', + rank: 12, + pic: './images/cards/queen_of_spades.png', + hold: false, + }, + { + name: 'jack', + suit: 'clubs', + rank: 11, + pic: './images/cards/jack_of_clubs.png', + hold: false, + }, + { + name: '10', + suit: 'hearts', + rank: 10, + pic: './images/cards/10_of_hearts.png', + hold: false, + }, + ], + suit: { + clubs: 1, + spades: 1, + hearts: 2, + diamonds: 1, + }, + name: { + 2: 0, + 3: 0, + 4: 0, + 5: 0, + 6: 0, + 7: 0, + 8: 0, + 9: 0, + 10: 1, + ace: 1, + jack: 1, + queen: 1, + king: 1, + }, +}; + +const flushHand = { + hand: [ + { + name: '2', + suit: 'hearts', + rank: 2, + pic: './images/cards/2_of_hearts.png', + hold: false, + }, + { + name: '4', + suit: 'hearts', + rank: 4, + pic: './images/cards/4_of_hearts.png', + hold: false, + }, + { + name: '6', + suit: 'hearts', + rank: 6, + pic: './images/cards/6_of_hearts.png', + hold: false, + }, + { + name: '8', + suit: 'hearts', + rank: 8, + pic: './images/cards/8_of_hearts.png', + hold: false, + }, + { + name: '10', + suit: 'hearts', + rank: 10, + pic: './images/cards/10_of_hearts.png', + hold: false, + }, + ], + suit: { + clubs: 0, + spades: 0, + hearts: 5, + diamonds: 0, + }, + name: { + 2: 1, + 3: 0, + 4: 1, + 5: 0, + 6: 1, + 7: 0, + 8: 1, + 9: 0, + 10: 1, + ace: 0, + jack: 0, + queen: 0, + king: 0, + }, +}; + +const jacksOrBetterHand = { + hand: [ + { + name: 'jack', + suit: 'diamonds', + rank: 11, + pic: './images/cards/jack_of_diamonds.png', + hold: false, + }, + { + name: 'jack', + suit: 'hearts', + rank: 11, + pic: './images/cards/jack_of_hearts.png', + hold: false, + }, + { + name: '2', + suit: 'spades', + rank: 2, + pic: './images/cards/2_of_spades.png', + hold: false, + }, + { + name: '4', + suit: 'clubs', + rank: 4, + pic: './images/cards/4_of_clubs.png', + hold: false, + }, + { + name: '6', + suit: 'hearts', + rank: 6, + pic: './images/cards/6_of_hearts.png', + hold: false, + }, + ], + suit: { + clubs: 1, + spades: 1, + hearts: 2, + diamonds: 1, + }, + name: { + 2: 1, + 3: 0, + 4: 1, + 5: 0, + 6: 1, + 7: 0, + 8: 0, + 9: 0, + 10: 0, + ace: 0, + jack: 2, + queen: 0, + king: 0, + }, +}; + +const testStraightFlushHand = { + hand: [ + { + name: '10', + suit: 'diamonds', + rank: 10, + pic: './images/cards/10_of_diamonds.png', + hold: false, + }, + { + name: '2', + suit: 'diamonds', + rank: 2, + pic: './images/cards/2_of_diamonds.png', + hold: false, + }, + { + name: '9', + suit: 'diamonds', + rank: 9, + pic: './images/cards/9_of_diamonds.png', + hold: false, + }, + { + name: 'jack', + suit: 'diamonds', + rank: 11, + pic: './images/cards/jack_of_diamonds.png', + hold: false, + }, + { + name: '5', + suit: 'diamonds', + rank: 5, + pic: './images/cards/5_of_diamonds.png', + hold: false, + }, + ], + suit: { + clubs: 0, + spades: 0, + hearts: 0, + diamonds: 5, + }, + name: { + 2: 1, + 3: 0, + 4: 0, + 5: 1, + 6: 0, + 7: 0, + 8: 0, + 9: 1, + 10: 0, + ace: 1, + jack: 1, + queen: 0, + king: 0, + }, +}; + +const testStraightFlushCardsLeft = { + ace: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 2: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 0, + }, + 3: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 4: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 5: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 0, + }, + 6: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 7: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 8: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + 9: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 0, + }, + 10: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 0, + }, + jack: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 0, + }, + queen: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, + king: { + clubs: 1, + spades: 1, + hearts: 1, + diamonds: 1, + }, +}; diff --git a/scripts/uiHelper.js b/scripts/uiHelper.js new file mode 100644 index 00000000..33bef24c --- /dev/null +++ b/scripts/uiHelper.js @@ -0,0 +1,172 @@ +/** + * + * To disable the button so that user cannot click it + * @param {String} id of button to be disabled + */ +const disableButton = (buttonId) => { + document.getElementById(buttonId).className = 'nes-btn is-disabled'; + document.getElementById(buttonId).disabled = true; +}; + +/** + * + * To enable the button so that user can click it + * @param {String} id of button to be enabled + */ +const enableButton = (buttonId) => { + document.getElementById(buttonId).classList.remove('is-disabled'); + document.getElementById(buttonId).disabled = false; + + if (buttonId === 'deal') { + document.getElementById(buttonId).classList.add('is-primary'); + } else if (buttonId === 'bet-1') { + document.getElementById(buttonId).classList.add('is-warning'); + } else if (buttonId === 'bet-5') { + document.getElementById(buttonId).classList.add('is-error'); + } else if (buttonId === 'calculate-probability') { + document.getElementById(buttonId).classList.add('is-normal'); + } +}; + +/** + * + * To designate cards that are to be held and cards that are to be replaced + * @param {String} id of card to be held + */ +const toggleHold = (cardId) => { + if (mode === 'firstDeal') { + if (document.getElementById(`hold-${cardId}`).className === 'unhold') { + document.getElementById(`hold-${cardId}`).className = 'hold'; + stats.hand[cardId].hold = true; + } else { + document.getElementById(`hold-${cardId}`).className = 'unhold'; + stats.hand[cardId].hold = false; + } + } +}; + +/** + * + * To update the display of player bet + */ +const updatePlayerBetUI = () => { + document.getElementById('player-bet').innerHTML = playerBet; +}; + +/** + * + * To update the display of player credits + */ +const updatePlayerCreditsUI = () => { + document.getElementById('player-credits').innerHTML = playerCredits; +}; + +/** + * + * To update the display of player instructions + */ +const updateInstructions = (instructions) => { + document.getElementById('instructions').innerHTML = instructions; +}; + +/** + * + * To update the cards displayed + */ +const updateCardsUI = () => { + let counter = 0; + + if (document.getElementById('cards').className === 'display-none') { + document.getElementById('cards').className = 'flex'; + } + + // clear any outstanding cards + for (let i = 0; i < 5; i += 1) { + document.getElementById(`card-${i}`).innerHTML = ''; + } + + const setCards = setInterval(() => { + const card = document.createElement('IMG'); + card.src = `${stats.hand[counter].pic}`; + card.id = `${counter}`; + + const cardDiv = document.getElementById(`card-${counter}`); + + card.addEventListener('click', (event) => { + toggleHold(event.target.id); + }); + + cardDiv.appendChild(card); + + const hold = document.createElement('div'); + hold.classList.add('unhold'); + hold.id = `hold-${counter}`; + hold.innerText = 'Hold'; + + hold.addEventListener('click', (event) => { + toggleHold(event.target.id.split('-')[1]); + }); + + cardDiv.appendChild(hold); + + if (counter === 4) { + clearInterval(setCards); + if (mode === 'firstDeal') { + enableButton('deal'); + } + } + + counter += 1; + }, 100); +}; + +/** + * + * To highlight the column of potential rewards depending on size of player bets + */ +const highlightRewardColumn = () => { + const scoreTable = document.getElementById('score-table'); + + for (let i = 0; i < scoreTable.rows.length; i += 1) { + for (let j = 0; j <= 5; j += 1) { + if (j === playerBet) { + scoreTable.rows[i].cells[j].style.color = '#209cee'; + } else { + scoreTable.rows[i].cells[j].style.color = 'white'; + } + } + } +}; + +/** + * + * To present long number properly with commas + * @param {Number} any number + * @returns {String} string of a number with properly denoted commas e.g. 1000000 -> 1,000,000 + */ +const numberWithCommas = (x) => x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ','); + +/** + * + * To update the total number of combinations available with current hand and cards to be replaced + * @param {Number} number of card combinations + */ +const updateTotalCombinationsAvailableUI = (totalCombinations) => { + document.getElementById('total-combinations').innerHTML = numberWithCommas(totalCombinations.toFixed(0)); +}; + +/** + * + * To update the respective probabilities for each winning hand + */ +const updateProbabilityUI = () => { + document.getElementById('probabilities').classList.remove('display-none'); + document.getElementById('probability-royal-flush').innerHTML = Number.parseFloat(probability.royalFlush).toFixed(5); + document.getElementById('probability-straight-flush').innerHTML = Number.parseFloat(probability.straightFlush).toFixed(5); + document.getElementById('probability-four-of-a-kind').innerHTML = Number.parseFloat(probability.fourOfAKind).toFixed(5); + document.getElementById('probability-full-house').innerHTML = Number.parseFloat(probability.fullHouse).toFixed(5); + document.getElementById('probability-flush').innerHTML = Number.parseFloat(probability.flush).toFixed(5); + document.getElementById('probability-straight').innerHTML = Number.parseFloat(probability.straight).toFixed(5); + document.getElementById('probability-three-of-a-kind').innerHTML = Number.parseFloat(probability.threeOfAKind).toFixed(5); + document.getElementById('probability-two-pair').innerHTML = Number.parseFloat(probability.twoPairs).toFixed(5); +}; diff --git a/styles.css b/styles.css new file mode 100644 index 00000000..d7584862 --- /dev/null +++ b/styles.css @@ -0,0 +1,81 @@ +*, +*:before, +*:after { + box-sizing: border-box; + font-family: "Press Start 2P", cursive; +} + +body { + background: #212529; +} + +#logo { + width: 100px; +} + +#score-table { + width: 100%; + font-size: 12px; + table-layout: auto; +} + +.hold { + color: #212529; + background: #f7d51d; + top: -50%; + position: relative; +} + +.unhold { + top: -50%; + position: relative; + display: none; +} + +#video-poker-machine { + width: 800px; + height: 1000px; + margin: 0 auto; + text-align: center; +} + +.nes-container { + width: 100%; +} + +.display-none { + display: none; +} + +.flex { + display: flex; +} + +.text-white { + color: white; +} + +.card { + width: 20%; + padding: 5px; +} + +.space-evenly { + justify-content: space-evenly; +} + +.align-items-center { + align-items: center; +} + +.text-align-center { + text-align: center; +} + +img { + width: 100%; +} + +#probabilities > p { + margin-bottom: 0; +}