diff --git a/README.md b/README.md index 15bb106..488181f 100644 --- a/README.md +++ b/README.md @@ -1 +1,26 @@ # javascript-lotto-precourse +## 기능 목록 +### 로또 금액 사용자 입력 +1. 사용자 금액 입력 처리 : 1000원 단위로 금액을 입력 받는다. (오류x) +2. 사용자 입력 처외 처리(오류1) : 1000단위 미만의 값을 입력 받으면 오류 메세지('[ERROR]')를 띄운다. +3. 사용자 입력 예외 처리(오류2) : 0원 이하의 값을 받으면 오류 메세지('[ERROR]')를 띄운다. +### 당첨 번호 사용자 입력 +1. 로또 수량 추출 : 사력자가 구매한 금액으로 부터 로또 수량을 추출한다. +2. 로또 뽑기 기능 구현 : 중복되지 않는 숫자 6개 set을 수량만큼 만든다.(1~45사이 숫자 랜덤 추출) +3. 사용자 입력 처리 : 당첨 번호 6개를 입력 받는다. +4. 사용자 입력 예외 처리 : 구분자 , 가 아니면 오류 메세지를 띄운다. +5. 사용자 입력 예외 처리 : 당첨번호가 6개가 아니면 오류 메세지를 띄운다. +6. 사용자 입력 예외 처리 : 당첨번호 숫자 1~45 사이의 숫자가 아니면 오류메세지를 띄운다. +7. 사용자 입력 처리 : 보너스 번호를 1개를 입력받는다. +8. 사용자 입력 예외처리 : 보너스 번호가 1개가 아니고, ',' 구분자자 들어가 있으면 오류메세지를 띄운다. +9. 사용자 입력 예외처리 : 보너스 번호 숫자 1~45 사이의 숫자가 아니면 오류메세지를 띄운다. +### 로또 수량 및 번호 출력 +1. 수량 출력 : 추출한 로또 수량을 출력한다. +2. 로또 번호 출력 : 로또 번호를 수량만큼 오름차순으로 출력한다. +3. 당첨 내역 출력 : 당첨 번호와 비교하여 번호 일치 개수를 추출한다. +4. 당첨 내역 출력 : 번호 일치 개수 만큼 분류하여 당첨 수량을 추출한다. + +### 수익률 계산 및 출력 +1. 수익률을 계산 : (당첨 금액/구매 금액) * 100 수식을 이용하여 수익률(%)을 구하고고소수 둘째 자리에서 반올림한다. +2. 수익률 출력 + diff --git a/src/App.js b/src/App.js index 091aa0a..434670b 100644 --- a/src/App.js +++ b/src/App.js @@ -1,5 +1,37 @@ +import { Console, Random } from "@woowacourse/mission-utils"; +import { getTicketCount, generateLottoTickets, parseWinningNumbers, parseBonusNumber } from "./LottoGame.js"; +import { calculateWinningCounts, printWinningStatistics } from "./LottoResult.js"; class App { - async run() {} + async run() { + + try{ + const moneyInput = await Console.readLineAsync('로또 구입 금액을 입력해주세요.\n'); + const purchaseAmount = Number(moneyInput) + const ticketCount = getTicketCount(purchaseAmount); + Console.print(ticketCount + '개의 로또를 구입했습니다.'); + + const tickets = generateLottoTickets(ticketCount); + tickets.forEach(function(ticket){ + Console.print (ticket.toString()); + }); + + const winningInput = await Console.readLineAsync('당첨 번호를 입력해주세요.\n'); + const winningNumbers = parseWinningNumbers(winningInput); + Console.print('당첨 번호 : ' + winningNumbers.join(', ')); + + const bonusInput = await Console.readLineAsync('보너스 번호를 입력해주세요.\n'); + const bonusNumber = parseBonusNumber(bonusInput); + Console.print('보너스 번호 : ' + bonusNumber); + + const winningCounts = calculateWinningCounts(tickets, winningNumbers, bonusNumber); + printWinningStatistics(winningCounts, purchaseAmount); + + } catch (error) { + Console.print([error.message]); + } + } } +const app = new App(); +app.run(); export default App; diff --git a/src/Lotto.js b/src/Lotto.js index cb0b152..7af5118 100644 --- a/src/Lotto.js +++ b/src/Lotto.js @@ -12,7 +12,14 @@ class Lotto { } } - // TODO: 추가 기능 구현 + toString(){ + return "[" +this.#numbers.join(', ') + "]"; + } + + // 당첨 계산에 사용될 로또 번호 배열 반환 + getNumbers() { + return this.#numbers; + } } export default Lotto; diff --git a/src/LottoGame.js b/src/LottoGame.js new file mode 100644 index 0000000..e6812b4 --- /dev/null +++ b/src/LottoGame.js @@ -0,0 +1,53 @@ +import { Random } from '@woowacourse/mission-utils'; +import Lotto from './Lotto.js'; +function getTicketCount(money) { + // 0원 이하 또는 1000원 단위가 아닐 경우 에러 처리 + if (money <= 0) throw new Error('[Error] 금액의 최소 구입 단위는 1000원 입니다.'); + if (money % 1000 !== 0) throw new Error('[Error] 1000원 단위로만 구입 가능합니다.'); + return money / 1000; +} + +function createLottoTicket() { + const numbers = Random.pickUniqueNumbersInRange(1, 45, 6); + numbers.sort(function(a, b){ return a -b; }); + return new Lotto(numbers); +} + +function generateLottoTickets(count){ + const tickets = []; + for (let i = 0; i < count; i++){ + tickets.push(createLottoTicket()); + } + return tickets; +} + +function parseWinningNumbers(input) { + if (input.indexOf(',') === -1) throw new Error('[Error] 구분자는 ,만 사용 가능합니다.'); + const parts = input.split(','); + if (parts.length !== 6) throw new Error('[Error] 로또 당첨 번호는 6개입니다.'); + const numbers = []; + for (let i = 0; i < parts.length; i++) { + const num = Number(parts[i].trim()); + if (isNaN(num) || num < 1 || num > 45) throw new Error ('[Error] 번호는 1 이상 45이하 범위의 숫자여야 합니다.'); + numbers.push(num); + } + numbers.sort(function(a,b) {return a - b ;}); + return numbers; +} + +function parseBonusNumber(input) { + if (input.indexOf(',') !== -1) throw new Error('[Error] 번호는 하나만 입력 가능합니다.'); + const num = Number(input.trim()); + if (isNaN(num) || num < 1 || num > 45) throw new Error('[Error] 번호는 1 이상 45이하 범위의 숫자여야 합니다.'); + return num; +} + +export { + getTicketCount, + createLottoTicket, + generateLottoTickets, + parseWinningNumbers, + parseBonusNumber +}; + + diff --git a/src/LottoResult.js b/src/LottoResult.js new file mode 100644 index 0000000..6b7067e --- /dev/null +++ b/src/LottoResult.js @@ -0,0 +1,72 @@ +import { Console } from '@woowacourse/mission-utils'; + +function calculateWinningCounts(tickets, winningNumbers, bonusNumber) { + // 당첨 번호 일치 개수 추출 + const counts = {}; + for (const ticket of tickets) { + + const numbers = ticket.getNumbers(); + const matchCount = numbers.filter(num => winningNumbers.includes(num)).length; + //Console.print(`티켓: [${numbers.join(', ')}], 일치 개수: ${matchCount}`); + + if (matchCount === 6) { + counts.six = (counts.six || 0) + 1; + continue; + } + if (matchCount === 5) { + if (numbers.includes(bonusNumber)) { + counts.bonus = (counts.bonus || 0) + 1; + } else { + counts.five = (counts.five || 0) + 1; + } + continue; + } + if (matchCount ===4 ) { + counts.four = (counts.four || 0) + 1; + continue; + } + if (matchCount ===3 ) { + counts.three = (counts.three || 0) +1; + } + } + return counts; +} + +function calculateTotalWinning(winningCounts) { +// 총 당첨 금액 계산 + const PRIZE_THREE = 5000; + const PRIZE_FOUR = 50000; + const PRIZE_FIVE = 1500000; + const PRIZE_BONUS = 30000000; + const PRIZE_SIX = 2000000000; + return ((winningCounts.three || 0) * PRIZE_THREE ) + + ((winningCounts.four || 0) * PRIZE_FOUR ) + + ((winningCounts.five || 0) * PRIZE_FIVE ) + + ( (winningCounts.bonus || 0) * PRIZE_BONUS ) + + ( (winningCounts.six || 0) * PRIZE_SIX ); +} + +function calculateYield(totalWinning, purchaseAmount){ + //수익률 계산 + return Math.round((totalWinning / purchaseAmount) * 1000) / 10; +} + +function printWinningStatistics(winningCounts, purchaseAmount) { + const three = winningCounts.three || 0; + const four = winningCounts.four || 0; + const five = winningCounts.five || 0; + const bonus = winningCounts.bonus || 0; + const six = winningCounts.six || 0; + const totalWinning = calculateTotalWinning(winningCounts); + const yieldRate = calculateYield(totalWinning, purchaseAmount); + Console.print('당첨 통계'); + Console.print('---') + Console.print(`3개 일치 (5,000원) - ${three}개`) + Console.print(`4개 일치 (50,000원) - ${four}개`) + Console.print(`5개 일치 (1,500,000원) - ${five}개`) + Console.print(`5개 일치, 보너스 볼 일치 (30,000,000원) - ${bonus}개`) + Console.print(`6개 일치 (2,000,000,000원) - ${six}개`) + Console.print(`총 수익률은 ${yieldRate}%입니다.`) +} + +export { calculateWinningCounts, calculateTotalWinning, calculateYield, printWinningStatistics }; \ No newline at end of file