diff --git a/src/app.js b/src/app.js index ad9a93a..f46f397 100644 --- a/src/app.js +++ b/src/app.js @@ -1 +1,41 @@ 'use strict'; + +const { generateNumber } = require('./generateNumber'); +const { calculateBullsAndCows } = require('./calculateBullsAndCows'); +const { terminal } = require('./userInterface'); +const { validateInput } = require('./validateInput'); +const { + QUESTION, + WINNER_MESSAGE, + INVALID_INPUT_MESSAGE, +} = require('./constants'); + +const generatedNumber = generateNumber(); + +function askQuestion() { + terminal.question(QUESTION, (userNumber) => { + const isInputValid = validateInput(userNumber); + + if (!isInputValid) { + terminal.write(INVALID_INPUT_MESSAGE); + askQuestion(); + + return; + } + + if (+userNumber === generatedNumber) { + terminal.write(WINNER_MESSAGE); + terminal.close(); + + return; + } + + const { bulls, cows } = calculateBullsAndCows(userNumber, generatedNumber); + const WRONG_GUESS_MESSAGE = `Bulls: ${bulls}, Cows: ${cows}\n`; + + terminal.write(WRONG_GUESS_MESSAGE); + askQuestion(); + }); +} + +askQuestion(); diff --git a/src/calculateBullsAndCows.js b/src/calculateBullsAndCows.js new file mode 100644 index 0000000..9856f63 --- /dev/null +++ b/src/calculateBullsAndCows.js @@ -0,0 +1,22 @@ +'use strict'; + +const { DEFAULT_ANSWER_VALUE } = require('./constants'); + +function calculateBullsAndCows(userNumber, generatedNumber) { + const userNumberSplited = userNumber.split(''); + const generatedStringNumber = String(generatedNumber); + + return userNumberSplited.reduce((acc, number, index) => { + if (number === generatedStringNumber[index]) { + acc.bulls++; + } else if (generatedStringNumber.includes(number)) { + acc.cows++; + } + + return acc; + }, { ...DEFAULT_ANSWER_VALUE }); +} + +module.exports = { + calculateBullsAndCows, +}; diff --git a/src/constants.js b/src/constants.js new file mode 100644 index 0000000..bfe0919 --- /dev/null +++ b/src/constants.js @@ -0,0 +1,20 @@ +'use strict'; + +const DEFAULT_ANSWER_VALUE = { + bulls: 0, + cows: 0, +}; + +const QUESTION = 'Please enter your 4-digit guess: '; +const INVALID_INPUT_MESSAGE = 'Expecting a number of 4 different digits\n'; +const WINNER_MESSAGE = "Congratulations! You've guessed the number!"; + +const EXPECTED_NUMBER_LENGTH = 4; + +module.exports = { + DEFAULT_ANSWER_VALUE, + QUESTION, + INVALID_INPUT_MESSAGE, + WINNER_MESSAGE, + EXPECTED_NUMBER_LENGTH, +}; diff --git a/src/generateNumber.js b/src/generateNumber.js new file mode 100644 index 0000000..7a5cec8 --- /dev/null +++ b/src/generateNumber.js @@ -0,0 +1,28 @@ +'use strict'; + +const { EXPECTED_NUMBER_LENGTH } = require('./constants'); + +function generateNumber() { + const digitsToInsert = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + const distinctDigits = []; + + while (distinctDigits.length < EXPECTED_NUMBER_LENGTH) { + let randomIndex = 0; + + if (!distinctDigits.length) { + randomIndex = Math.floor(Math.random() * (digitsToInsert.length - 1) + 1); + } else { + randomIndex = Math.floor(Math.random() * digitsToInsert.length); + } + + const digitToInsert = digitsToInsert.splice(randomIndex, 1)[0]; + + distinctDigits.push(digitToInsert); + } + + return +distinctDigits.join(''); +} + +module.exports = { + generateNumber, +}; diff --git a/src/userInterface.js b/src/userInterface.js new file mode 100644 index 0000000..addffef --- /dev/null +++ b/src/userInterface.js @@ -0,0 +1,12 @@ +'use strict'; + +const readline = require('readline'); + +const terminal = readline.createInterface({ + input: process.stdin, + output: process.stdout, +}); + +module.exports = { + terminal, +}; diff --git a/src/validateInput.js b/src/validateInput.js new file mode 100644 index 0000000..dc3a20e --- /dev/null +++ b/src/validateInput.js @@ -0,0 +1,17 @@ +'use strict'; + +const { EXPECTED_NUMBER_LENGTH } = require('./constants'); + +function validateInput(input) { + const inputSplited = input.split(''); + const inputSet = new Set(inputSplited); + const isNumber = inputSplited.every(num => num >= 0 && num <= 9); + const hasValidLength = inputSplited.length === EXPECTED_NUMBER_LENGTH; + const hasDistinctDigits = inputSplited.length === inputSet.size; + + return hasValidLength && hasDistinctDigits && isNumber; +}; + +module.exports = { + validateInput, +};