From 6224d546341713dfb544f4ce39aac009724ca5f9 Mon Sep 17 00:00:00 2001 From: "YongRae_Kim (Usage)" Date: Mon, 28 Feb 2022 12:09:47 +0900 Subject: [PATCH 01/23] =?UTF-8?q?docs:=20todo=20list=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/todo.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/todo.md b/docs/todo.md index b3f3764c5c..ef3f69dea3 100644 --- a/docs/todo.md +++ b/docs/todo.md @@ -12,10 +12,12 @@ - [✅] 로또 모델에 숫자 배열을 인자로 넣어서 인스턴스를 생성할 수 있다. - [✅] 로또 모델의 배열에 들어갈 값은 1이상 45이하의 숫자여야 한다. - [✅] 로또 모델에 들어갈 배열의 길이는 6이어야 한다. -- [✅] 로또 모델의 번호와 당첨 번호를 비교하여 등수를 반환할 수 있어야 한다. +- [ ] 로또 모델의 번호와 당첨 번호를 비교하여 등수를 반환할 수 있어야 한다. **로또 게임 모델** - [✅] 로또 게임 모델에 금액이 정상적으로 입력되면, 구매할 수 있는 로또의 수를 반환할 수 있어야 한다. - [✅] 금액은 1000이상의 숫자여야한다. - [✅] 로또 번호 배열들을 입력하여 로또 모델을 생성하고 관리할 수 있어야 한다. +- [ ] 당첨 결과를 이용하여 당첨 통계와 수익률을 반환할 수 있어야 한다. +- [ ] 게임 초기화가 가능해야 한다. From f1e648a9bb72e1c543873ff23bddfd7a216638cf Mon Sep 17 00:00:00 2001 From: "YongRae_Kim (Usage)" Date: Mon, 28 Feb 2022 12:47:48 +0900 Subject: [PATCH 02/23] =?UTF-8?q?feat:=20=EB=A1=9C=EB=98=90=20=EB=AA=A8?= =?UTF-8?q?=EB=8D=B8=EC=97=90=EC=84=9C=20=EB=93=B1=EC=88=98=20=EB=B0=98?= =?UTF-8?q?=ED=99=98=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/todo.md | 2 +- src/js/__tests__/lotto.test.js | 11 +++++++++++ src/js/constants/number.js | 1 + src/js/models/Lotto.js | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 46 insertions(+), 1 deletion(-) diff --git a/docs/todo.md b/docs/todo.md index ef3f69dea3..97ec260c1a 100644 --- a/docs/todo.md +++ b/docs/todo.md @@ -12,7 +12,7 @@ - [✅] 로또 모델에 숫자 배열을 인자로 넣어서 인스턴스를 생성할 수 있다. - [✅] 로또 모델의 배열에 들어갈 값은 1이상 45이하의 숫자여야 한다. - [✅] 로또 모델에 들어갈 배열의 길이는 6이어야 한다. -- [ ] 로또 모델의 번호와 당첨 번호를 비교하여 등수를 반환할 수 있어야 한다. +- [✅] 로또 모델의 번호와 당첨 번호를 비교하여 등수를 반환할 수 있어야 한다. **로또 게임 모델** diff --git a/src/js/__tests__/lotto.test.js b/src/js/__tests__/lotto.test.js index 3e74f9abd7..18781b03c7 100644 --- a/src/js/__tests__/lotto.test.js +++ b/src/js/__tests__/lotto.test.js @@ -1,3 +1,6 @@ +/* eslint-disable max-lines-per-function */ +/* eslint-disable no-undef */ + import { ERROR_MESSAGE } from '../constants/errorMessage'; import Lotto from '../models/Lotto'; @@ -15,4 +18,12 @@ describe('로또 모델 테스트', () => { expect(message).toEqual(ERROR_MESSAGE.LOTTO_NUMBER_IS_INVALIDATE); } }); + + it('로또 모델의 번호와 당첨 번호를 비교하여 등수를 반환할 수 있어야 한다.', () => { + const lottoNumbers = [1, 2, 3, 4, 5, 6]; + const winningNumbers = [1, 2, 3, 4, 5, 7, 6]; + + const lotto = Lotto.create(lottoNumbers); + expect(lotto.result(winningNumbers)).toBe(2); + }); }); diff --git a/src/js/constants/number.js b/src/js/constants/number.js index eb3fde7d7d..a516cb33b6 100644 --- a/src/js/constants/number.js +++ b/src/js/constants/number.js @@ -3,4 +3,5 @@ export const NUMBER = { LOTTO_MIN_NUMBER: 1, LOTTO_MAX_NUMBER: 45, LOTTO_PRICE: 1000, + BONUS_NUMBER: 6, }; diff --git a/src/js/models/Lotto.js b/src/js/models/Lotto.js index df43855bfa..b6f134212a 100644 --- a/src/js/models/Lotto.js +++ b/src/js/models/Lotto.js @@ -1,5 +1,6 @@ import { isValidNumber, isValidLength } from '../utils/validator'; import { ERROR_MESSAGE } from '../constants/errorMessage'; +import { NUMBER } from '../constants/number'; class Lotto { constructor(lottoNumbers) { @@ -12,6 +13,38 @@ class Lotto { } throw new Error(ERROR_MESSAGE.LOTTO_NUMBER_IS_INVALIDATE); } + + result(winningNumbers) { + let countMatchNumber = 0; + let isContainBonusNumber = false; + + this.lottoNumbers.forEach((number) => { + if (winningNumbers.includes(number)) { + countMatchNumber += 1; + if (number === winningNumbers[NUMBER.BONUS_NUMBER]) { + isContainBonusNumber = true; + } + } + }); + + return this.getLottoScore(countMatchNumber, isContainBonusNumber); + } + + getLottoScore(countMatchNumber, isContainBonusNumber) { + switch (countMatchNumber) { + case 3: + return 5; + case 4: + return 4; + case 5: + return 3; + case 6: + if (isContainBonusNumber) return 2; + return 1; + default: + return 0; + } + } } export default Lotto; From d4cadf9ad1f7d95a5d6354f1ce9a6005c3175fe4 Mon Sep 17 00:00:00 2001 From: "YongRae_Kim (Usage)" Date: Mon, 28 Feb 2022 21:41:27 +0900 Subject: [PATCH 03/23] =?UTF-8?q?feat:=20=EB=8B=B9=EC=B2=A8=20=EA=B2=B0?= =?UTF-8?q?=EA=B3=BC=EB=A5=BC=20=EC=9D=B4=EC=9A=A9=ED=95=98=EC=97=AC=20?= =?UTF-8?q?=ED=86=B5=EA=B3=84=EC=99=80=20=EC=88=98=EC=9D=B5=EB=A5=A0?= =?UTF-8?q?=EC=9D=84=20=EB=B0=98=ED=99=98=ED=95=A0=20=EC=88=98=20=EC=9E=88?= =?UTF-8?q?=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/todo.md | 2 +- src/js/__tests__/lotto.test.js | 3 ++- src/js/__tests__/lottoGame.test.js | 19 ++++++++++++++++++- src/js/constants/number.js | 12 ++++++++++++ src/js/models/Lotto.js | 16 ++++++++-------- src/js/models/LottoGame.js | 24 ++++++++++++++++++++++++ 6 files changed, 65 insertions(+), 11 deletions(-) diff --git a/docs/todo.md b/docs/todo.md index 97ec260c1a..be77cdd468 100644 --- a/docs/todo.md +++ b/docs/todo.md @@ -19,5 +19,5 @@ - [✅] 로또 게임 모델에 금액이 정상적으로 입력되면, 구매할 수 있는 로또의 수를 반환할 수 있어야 한다. - [✅] 금액은 1000이상의 숫자여야한다. - [✅] 로또 번호 배열들을 입력하여 로또 모델을 생성하고 관리할 수 있어야 한다. -- [ ] 당첨 결과를 이용하여 당첨 통계와 수익률을 반환할 수 있어야 한다. +- [✅] 당첨 결과를 이용하여 당첨 통계와 수익률을 반환할 수 있어야 한다. - [ ] 게임 초기화가 가능해야 한다. diff --git a/src/js/__tests__/lotto.test.js b/src/js/__tests__/lotto.test.js index 18781b03c7..9a8c6fdb78 100644 --- a/src/js/__tests__/lotto.test.js +++ b/src/js/__tests__/lotto.test.js @@ -2,6 +2,7 @@ /* eslint-disable no-undef */ import { ERROR_MESSAGE } from '../constants/errorMessage'; +import { NUMBER } from '../constants/number'; import Lotto from '../models/Lotto'; describe('로또 모델 테스트', () => { @@ -24,6 +25,6 @@ describe('로또 모델 테스트', () => { const winningNumbers = [1, 2, 3, 4, 5, 7, 6]; const lotto = Lotto.create(lottoNumbers); - expect(lotto.result(winningNumbers)).toBe(2); + expect(lotto.result(winningNumbers)).toBe(NUMBER.SECOND_GRADE_INDEX); }); }); diff --git a/src/js/__tests__/lottoGame.test.js b/src/js/__tests__/lottoGame.test.js index 52ed9d55c9..45ed26d09c 100644 --- a/src/js/__tests__/lottoGame.test.js +++ b/src/js/__tests__/lottoGame.test.js @@ -1,6 +1,10 @@ +/* eslint-disable max-lines-per-function */ +/* eslint-disable no-undef */ + import '../utils/customPrototypeMethod'; import { ERROR_MESSAGE } from '../constants/errorMessage'; import LottoGame from '../models/LottoGame'; +import Lotto from '../models/Lotto'; describe('로또 게임 모델 테스트', () => { it('로또 게임 모델에 금액이 정상적으로 입력되면, 구매할 수 있는 로또의 수를 반환할 수 있어야 한다.', () => { @@ -31,7 +35,6 @@ describe('로또 게임 모델 테스트', () => { expect(lottoGame.lottoList.length).toBe(availableLottoAmount); }); - /** 이 부분이 lottoGame의 테스트인지, 유틸 함수에 대한 테스트인지 궁금하다. */ it('lottoList의 getter는 깊게 복사된 값을 반환한다.', () => { const lottoGame = new LottoGame(); const charge = 5000; @@ -41,4 +44,18 @@ describe('로또 게임 모델 테스트', () => { const lottoListFromGetterFunc = lottoGame.getLottoList(); expect(lottoListFromGetterFunc).toEqual(lottoGame.lottoList); }); + + it('당첨 결과를 이용하여 당첨 통계와 수익률을 반환할 수 있어야 한다.', () => { + const lottoGame = new LottoGame(); + const lottoList = []; + const winningNumbers = [1, 2, 3, 4, 5, 6]; + const result = [1, 0, 1, 1, 0, 667183, 0]; + + lottoList.push(Lotto.create([1, 2, 3, 4, 5, 6])); + lottoList.push(Lotto.create([1, 2, 3, 4, 5, 7])); + lottoList.push(Lotto.create([1, 2, 3, 4, 7, 8])); + + lottoGame.lottoList = lottoList; + expect(lottoGame.getGameResult(winningNumbers)).toEqual(result); + }); }); diff --git a/src/js/constants/number.js b/src/js/constants/number.js index a516cb33b6..cad578ffad 100644 --- a/src/js/constants/number.js +++ b/src/js/constants/number.js @@ -4,4 +4,16 @@ export const NUMBER = { LOTTO_MAX_NUMBER: 45, LOTTO_PRICE: 1000, BONUS_NUMBER: 6, + FIRST_GRADE_PRIZE: 2000000000, + SECOND_GRADE_PRIZE: 30000000, + THIRD_GRADE_PRIZE: 1500000, + FOURTH_GRADE_PRIZE: 50000, + FIFTH_GRADE_PRIZE: 5000, + FIRST_GRADE_INDEX: 0, + SECOND_GRADE_INDEX: 1, + THIRD_GRADE_INDEX: 2, + FOURTH_GRADE_INDEX: 3, + FIFTH_GRADE_INDEX: 4, + EARNING_RATE_INDEX: 5, + NOT_WINNING_INDEX: 6, }; diff --git a/src/js/models/Lotto.js b/src/js/models/Lotto.js index b6f134212a..3a282efedf 100644 --- a/src/js/models/Lotto.js +++ b/src/js/models/Lotto.js @@ -27,22 +27,22 @@ class Lotto { } }); - return this.getLottoScore(countMatchNumber, isContainBonusNumber); + return this.getLottoRank(countMatchNumber, isContainBonusNumber); } - getLottoScore(countMatchNumber, isContainBonusNumber) { + getLottoRank(countMatchNumber, isContainBonusNumber) { switch (countMatchNumber) { case 3: - return 5; + return NUMBER.FIFTH_GRADE_INDEX; case 4: - return 4; + return NUMBER.FOURTH_GRADE_INDEX; case 5: - return 3; + return NUMBER.THIRD_GRADE_INDEX; case 6: - if (isContainBonusNumber) return 2; - return 1; + if (isContainBonusNumber) return NUMBER.SECOND_GRADE_INDEX; + return NUMBER.FIRST_GRADE_INDEX; default: - return 0; + return NUMBER.NOT_WINNING_INDEX; } } } diff --git a/src/js/models/LottoGame.js b/src/js/models/LottoGame.js index e0c18005a1..bf58ea9295 100644 --- a/src/js/models/LottoGame.js +++ b/src/js/models/LottoGame.js @@ -6,6 +6,7 @@ import { NUMBER } from '../constants/number'; class LottoGameModel { constructor() { this.lottoList = []; + this.winningResult = [0, 0, 0, 0, 0, 0, 0]; } getLottoList() { @@ -43,6 +44,29 @@ class LottoGameModel { } throw new Error(ERROR_MESSAGE.CHARGE_IS_INVALIDATE); } + + getGameResult(winningNumbers) { + this.lottoList.forEach((lotto) => { + this.updateLottoRankResult(lotto, winningNumbers); + }); + this.updateLottoEarningRate(); + return this.winningResult; + } + + updateLottoRankResult(lotto, winningNumbers) { + this.winningResult[lotto.result(winningNumbers)] += 1; + } + + updateLottoEarningRate() { + const totalCharge = this.lottoList.length * NUMBER.LOTTO_PRICE; + const totalWinningMoney = + NUMBER.FIRST_GRADE_PRIZE * this.winningResult[NUMBER.FIRST_GRADE_INDEX] + + NUMBER.SECOND_GRADE_PRIZE * this.winningResult[NUMBER.SECOND_GRADE_INDEX] + + NUMBER.THIRD_GRADE_PRIZE * this.winningResult[NUMBER.THIRD_GRADE_INDEX] + + NUMBER.FOURTH_GRADE_PRIZE * this.winningResult[NUMBER.FOURTH_GRADE_INDEX] + + NUMBER.FIFTH_GRADE_PRIZE * this.winningResult[NUMBER.FIFTH_GRADE_INDEX]; + this.winningResult[NUMBER.EARNING_RATE_INDEX] = Math.floor(totalWinningMoney / totalCharge); + } } export default LottoGameModel; From 19039ca7aaba4e340c81fd362e0f95059ab70a03 Mon Sep 17 00:00:00 2001 From: "YongRae_Kim (Usage)" Date: Tue, 1 Mar 2022 18:44:13 +0900 Subject: [PATCH 04/23] =?UTF-8?q?feat:=20=EA=B2=8C=EC=9E=84=20=EC=B4=88?= =?UTF-8?q?=EA=B8=B0=ED=99=94=EA=B0=80=20=EA=B0=80=EB=8A=A5=ED=95=B4?= =?UTF-8?q?=EC=95=BC=20=ED=95=9C=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/todo.md | 2 +- src/js/__tests__/lottoGame.test.js | 15 ++++++++++++--- src/js/models/LottoGame.js | 4 ++++ 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/docs/todo.md b/docs/todo.md index be77cdd468..dbadc1d0e5 100644 --- a/docs/todo.md +++ b/docs/todo.md @@ -20,4 +20,4 @@ - [✅] 금액은 1000이상의 숫자여야한다. - [✅] 로또 번호 배열들을 입력하여 로또 모델을 생성하고 관리할 수 있어야 한다. - [✅] 당첨 결과를 이용하여 당첨 통계와 수익률을 반환할 수 있어야 한다. -- [ ] 게임 초기화가 가능해야 한다. +- [✅] 게임 초기화가 가능해야 한다. diff --git a/src/js/__tests__/lottoGame.test.js b/src/js/__tests__/lottoGame.test.js index 45ed26d09c..ead53089cf 100644 --- a/src/js/__tests__/lottoGame.test.js +++ b/src/js/__tests__/lottoGame.test.js @@ -6,10 +6,11 @@ import { ERROR_MESSAGE } from '../constants/errorMessage'; import LottoGame from '../models/LottoGame'; import Lotto from '../models/Lotto'; +const charge = 5000; + describe('로또 게임 모델 테스트', () => { it('로또 게임 모델에 금액이 정상적으로 입력되면, 구매할 수 있는 로또의 수를 반환할 수 있어야 한다.', () => { const lottoGame = new LottoGame(); - const charge = 5000; const expectedAvailableLottoAmount = 5; const availableLottoAmount = lottoGame.exchangeChargeToLottoAmount(charge); expect(availableLottoAmount).toBe(expectedAvailableLottoAmount); @@ -27,7 +28,6 @@ describe('로또 게임 모델 테스트', () => { it('로또 번호 배열들을 입력하여 로또 모델을 생성하고 관리할 수 있어야 한다.', () => { const lottoGame = new LottoGame(); - const charge = 5000; const availableLottoAmount = lottoGame.exchangeChargeToLottoAmount(charge); lottoGame.createLottoList(charge); @@ -37,7 +37,6 @@ describe('로또 게임 모델 테스트', () => { it('lottoList의 getter는 깊게 복사된 값을 반환한다.', () => { const lottoGame = new LottoGame(); - const charge = 5000; lottoGame.createLottoList(charge); @@ -58,4 +57,14 @@ describe('로또 게임 모델 테스트', () => { lottoGame.lottoList = lottoList; expect(lottoGame.getGameResult(winningNumbers)).toEqual(result); }); + + it('게임 초기화가 가능해야 한다.', () => { + const lottoGame = new LottoGame(); + const initializedLottoGame = new LottoGame(); + + lottoGame.createLottoList(charge); + lottoGame.initialize(); + + expect(lottoGame).toEqual(initializedLottoGame); + }); }); diff --git a/src/js/models/LottoGame.js b/src/js/models/LottoGame.js index bf58ea9295..7ce41b3fea 100644 --- a/src/js/models/LottoGame.js +++ b/src/js/models/LottoGame.js @@ -5,6 +5,10 @@ import { NUMBER } from '../constants/number'; class LottoGameModel { constructor() { + this.initialize(); + } + + initialize() { this.lottoList = []; this.winningResult = [0, 0, 0, 0, 0, 0, 0]; } From fc6104fc297c362e3d3c86ff0131e52fea5fa7c4 Mon Sep 17 00:00:00 2001 From: "YongRae_Kim (Usage)" Date: Tue, 1 Mar 2022 22:07:57 +0900 Subject: [PATCH 05/23] =?UTF-8?q?feat:=20=EA=B2=B0=EA=B3=BC=20=EB=AA=A8?= =?UTF-8?q?=EB=8B=AC=EC=B0=BD=20=EB=A7=88=ED=81=AC=20=EC=97=85=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- images/modal_close_button.png | Bin 0 -> 275 bytes index.html | 49 +++++++++++++++++++++++- src/css/index.css | 25 ++++++++++-- src/css/modal.css | 70 ++++++++++++++++++++++++++++++++++ src/index.js | 1 + 5 files changed, 139 insertions(+), 6 deletions(-) create mode 100644 images/modal_close_button.png create mode 100644 src/css/modal.css diff --git a/images/modal_close_button.png b/images/modal_close_button.png new file mode 100644 index 0000000000000000000000000000000000000000..8afcd0dda9a5ce6f278c7e71fe06ed329b16eb74 GIT binary patch literal 275 zcmeAS@N?(olHy`uVBq!ia0vp^d?3uh1|;P@bT0xa&H|6fVg?3oVGw3ym^DWND9BhG z!1;mn0^h&3#zmwn2;r8|``xCDlRhQiN R_ygU{;OXk;vd$@?2>=QoUxNSu literal 0 HcmV?d00001 diff --git a/index.html b/index.html index 295fc452b2..6746d2677b 100644 --- a/index.html +++ b/index.html @@ -11,7 +11,7 @@

🎱 행운의 로또

금액을 입력하는 섹션입니다.

-

구입할 금액을 입력해주세요

+

구입할 금액을 입력해주세요.

@@ -37,7 +37,9 @@

구매한 로또를 확인하는 섹션입

당첨 번호 입력 섹션

-

지난 주 당첨번호 6개와 보너스 번호 1개를 입력해주세요.

+

+ 지난 주 당첨번호 6개와 보너스 번호 1개를 입력해주세요. +

@@ -60,6 +62,49 @@

당첨 번호 입력 섹션

+ +
+
+ +
+
diff --git a/src/css/index.css b/src/css/index.css index daca1a1306..b4cae8d43d 100644 --- a/src/css/index.css +++ b/src/css/index.css @@ -9,11 +9,12 @@ input { } body { - width: 98vw; - height: 90vh; + width: 100vw; + height: 100vh; margin: auto; background-color: rgba(0, 0, 0, 0.07); font-family: 'NanumBarunGothic', sans-serif; + font-size: 1.1rem; display: flex; justify-content: center; @@ -23,7 +24,7 @@ body { #app { width: 25vw; min-width: 414px; - padding: 50px; + padding: 20px; background-color: #ffffff; border: 1px solid rgba(0, 0, 0, 0.12); @@ -46,12 +47,17 @@ body { border-radius: 4px; } +#charge-button { + width: 15%; +} + button { border-radius: 4px; background-color: #00bcd4; color: #ffffff; border: 0; min-height: 36px; + font-weight: bold; } section { @@ -80,7 +86,7 @@ section { } #lotto-container[data-visible-state='false'] { flex-direction: row; - gap: 10px; + gap: 3px; } #lotto-container[data-visible-state='false'] .number { @@ -97,6 +103,14 @@ section { gap: 10px; } +#win-number-input-section { + margin-top: 40px; +} + +.win-number-input-notice { + margin-bottom: 0; +} + .win-number-input-wrapper { display: flex; gap: 10px; @@ -106,17 +120,20 @@ section { #result-button { width: 100%; margin-top: 10px; + padding: 13px; } .win-number-input-wrapper input { width: 30px; height: 30px; + font-size: 1.3rem; } .bonus-number-wrapper { display: flex; align-items: flex-end; flex-direction: column; + margin-bottom: 20px; } #align-converter-container { diff --git a/src/css/modal.css b/src/css/modal.css new file mode 100644 index 0000000000..2bc92887aa --- /dev/null +++ b/src/css/modal.css @@ -0,0 +1,70 @@ +#result-modal-area[data-visible-state='false'] { + display: none; +} + +#result-modal-area[data-visible-state='true'] { + width: 100vw; + height: 100vh; + position: absolute; + left: 0; + top: 0; +} + +.background-area { + display: flex; + align-items: center; + justify-content: center; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.5); +} + +.modal { + background: #ffffff; + width: 25vw; + border-radius: 4px; + margin: auto; + text-align: center; + padding: 1rem; +} + +.winning-statistics-table { + padding: 1rem; +} + +.winning-statistics-table > li { + display: grid; + grid-template-columns: repeat(3, 1fr); + grid-gap: 10px; + border-bottom: 1px solid #dcdcdc; +} + +.table-head { + border-top: 1px solid #dcdcdc; + font-weight: bold; +} + +#modal-close-button { + width: 14px; + min-height: 14px; + background: no-repeat; + background-image: url('../../images/modal_close_button.png'); + position: relative; + right: -49%; + top: 0; +} + +.modal-title { + margin-top: 0; +} + +#earning-rate-notice { + font-weight: bold; + font-size: 1.2rem; +} + +#replay-button { + font-size: 1rem; + margin: 1rem 0 2rem 0; + padding: 0.8rem 2.5rem; +} diff --git a/src/index.js b/src/index.js index fddec6c039..5560727b68 100644 --- a/src/index.js +++ b/src/index.js @@ -1,5 +1,6 @@ import './css/index.css'; import './css/converter.css'; +import './css/modal.css'; import './css/nanumbarungothic.css'; import './js/utils/customPrototypeMethod'; import RacingGameManager from './js/app'; From ce1ecb428d4b4bcbf4ed6ac6c80c6803ed6358a1 Mon Sep 17 00:00:00 2001 From: "YongRae_Kim (Usage)" Date: Wed, 2 Mar 2022 17:31:36 +0900 Subject: [PATCH 06/23] =?UTF-8?q?feat:=20=EA=B2=B0=EA=B3=BC=EB=A5=BC=20?= =?UTF-8?q?=EB=B3=B4=EC=97=AC=EC=A3=BC=EB=8A=94=20modal=20view=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 10 ++++----- src/js/__tests__/lottoGame.test.js | 2 +- src/js/app.js | 35 ++++++++++++++++++++++++++++-- src/js/constants/selector.js | 13 +++++++++++ src/js/models/LottoGame.js | 1 + src/js/views/index.js | 27 +++++++++++++++++++++++ 6 files changed, 80 insertions(+), 8 deletions(-) diff --git a/index.html b/index.html index 6746d2677b..a23df90cbc 100644 --- a/index.html +++ b/index.html @@ -77,27 +77,27 @@
  • 3개

    5,000

    -

    n개

    +

    n개

  • 4개

    50,000

    -

    n개

    +

    n개

  • 5개

    1,500,000

    -

    n개

    +

    n개

  • 5개+보너스볼

    30,000,000

    -

    n개

    +

    n개

  • 6개

    2,000,000,000

    -

    n개

    +

    n개

  • 당신의 총 수익률은 %입니다.

    diff --git a/src/js/__tests__/lottoGame.test.js b/src/js/__tests__/lottoGame.test.js index ead53089cf..b88dccc6e3 100644 --- a/src/js/__tests__/lottoGame.test.js +++ b/src/js/__tests__/lottoGame.test.js @@ -47,7 +47,7 @@ describe('로또 게임 모델 테스트', () => { it('당첨 결과를 이용하여 당첨 통계와 수익률을 반환할 수 있어야 한다.', () => { const lottoGame = new LottoGame(); const lottoList = []; - const winningNumbers = [1, 2, 3, 4, 5, 6]; + const winningNumbers = [1, 2, 3, 4, 5, 6, 10]; const result = [1, 0, 1, 1, 0, 667183, 0]; lottoList.push(Lotto.create([1, 2, 3, 4, 5, 6])); diff --git a/src/js/app.js b/src/js/app.js index b7e254c30c..49c60e0f3b 100644 --- a/src/js/app.js +++ b/src/js/app.js @@ -7,13 +7,17 @@ class LottoGameManager { init() { this.lottoGameModel = new LottoGameModel(); this.lottoGameView = new LottoGameView(); - this.$chargeForm = findElement(SELECTOR.CHARGE_INPUT_FORM); this.$chargeInput = findElement(SELECTOR.CHARGE_INPUT); this.$alignConverter = findElement(SELECTOR.ALIGN_CONVERTER); - + this.$winNumberForm = findElement(SELECTOR.WIN_NUMBER_INPUT_FORM); + this.$modalCloseButton = findElement(SELECTOR.MODAL_CLOSE_BUTTON); + this.$replayButton = findElement(SELECTOR.REPLAY_BUTTON); this.$chargeForm.addEventListener('submit', this.onSubmitChargeInputForm); this.$alignConverter.addEventListener('change', this.onChangeAlignState); + this.$winNumberForm.addEventListener('submit', this.onSubmitWinNumberInputForm); + this.$replayButton.addEventListener('click', this.onClickReplayButton); + this.$modalCloseButton.addEventListener('click', this.onClickCloseModalButton); } onSubmitChargeInputForm = (e) => { @@ -39,5 +43,32 @@ class LottoGameManager { const { checked: alignState } = e.target; this.lottoGameView.renderAlignState(alignState); }; + + onSubmitWinNumberInputForm = (e) => { + e.preventDefault(); + const inputWinNumber = [ + Number(e.path[0][0].value), + Number(e.path[0][1].value), + Number(e.path[0][2].value), + Number(e.path[0][3].value), + Number(e.path[0][4].value), + Number(e.path[0][5].value), + Number(e.path[0][6].value), + ]; + const gameResult = this.lottoGameModel.getGameResult(inputWinNumber); + this.lottoGameView.openResultModal(gameResult); + }; + + onClickReplayButton = () => { + this.lottoGameModel.initialize(); + this.lottoGameView.initialize(); + this.$chargeForm.reset(); + this.$winNumberForm.reset(); + this.lottoGameView.closeResultModal(); + }; + + onClickCloseModalButton = () => { + this.lottoGameView.closeResultModal(); + }; } export default LottoGameManager; diff --git a/src/js/constants/selector.js b/src/js/constants/selector.js index e12365e7aa..9ca43d8950 100644 --- a/src/js/constants/selector.js +++ b/src/js/constants/selector.js @@ -1,8 +1,21 @@ export const SELECTOR = { CHARGE_INPUT_FORM: '#charge-input-form', CHARGE_INPUT: '#charge-input', + WIN_NUMBER_INPUT_FORM: '#win-number-input-form', + WIN_NUMBER_INPUT: '#win-number-', ALIGN_CONVERTER: '#align-converter', PURCHASED_MESSAGE: '#purchased-message', LOTTO_CONTAINER: '#lotto-container', + + RESULT_MODAL: '#result-modal-area', + EARNING_RATE_NOTICE: '#earning-rate-notice', + MODAL_CLOSE_BUTTON: '#modal-close-button', + REPLAY_BUTTON: '#replay-button', + + FIRST_GRADE_AMOUNT: '#first-grade-amount', + SECOND_GRADE_AMOUNT: '#second-grade-amount', + THIRD_GRADE_AMOUNT: '#third-grade-amount', + FOURTH_GRADE_AMOUNT: '#fourth-grade-amount', + FIFTH_GRADE_AMOUNT: '#fifth-grade-amount', }; diff --git a/src/js/models/LottoGame.js b/src/js/models/LottoGame.js index 7ce41b3fea..995f6a2a68 100644 --- a/src/js/models/LottoGame.js +++ b/src/js/models/LottoGame.js @@ -50,6 +50,7 @@ class LottoGameModel { } getGameResult(winningNumbers) { + this.winningResult = [0, 0, 0, 0, 0, 0, 0]; this.lottoList.forEach((lotto) => { this.updateLottoRankResult(lotto, winningNumbers); }); diff --git a/src/js/views/index.js b/src/js/views/index.js index 7591335071..04849ccf22 100644 --- a/src/js/views/index.js +++ b/src/js/views/index.js @@ -5,6 +5,18 @@ class LottoGameView { constructor() { this.$purchasedMessage = findElement(SELECTOR.PURCHASED_MESSAGE); this.$lottoContainer = findElement(SELECTOR.LOTTO_CONTAINER); + this.$resultModal = findElement(SELECTOR.RESULT_MODAL); + this.$earningRateNotice = findElement(SELECTOR.EARNING_RATE_NOTICE); + this.$firstGradeAmount = findElement(SELECTOR.FIRST_GRADE_AMOUNT); + this.$secondGradeAmount = findElement(SELECTOR.SECOND_GRADE_AMOUNT); + this.$thirdGradeAmount = findElement(SELECTOR.THIRD_GRADE_AMOUNT); + this.$fourthGradeAmount = findElement(SELECTOR.FOURTH_GRADE_AMOUNT); + this.$fifthGradeAmount = findElement(SELECTOR.FIFTH_GRADE_AMOUNT); + } + + initialize() { + this.$purchasedMessage.innerText = ''; + this.$lottoContainer.innerHTML = ''; } renderLottoSection(lottoList) { @@ -24,5 +36,20 @@ class LottoGameView { renderAlignState(visibleState) { this.$lottoContainer.setAttribute('data-visible-state', visibleState); } + + openResultModal(resultArray) { + this.$firstGradeAmount.innerText = `${resultArray[0]}개`; + this.$secondGradeAmount.innerText = `${resultArray[1]}개`; + this.$thirdGradeAmount.innerText = `${resultArray[2]}개`; + this.$fourthGradeAmount.innerText = `${resultArray[3]}개`; + this.$fifthGradeAmount.innerText = `${resultArray[4]}개`; + this.$earningRateNotice.innerText = `당신의 총 수익률은 ${resultArray[5]}%입니다.`; + + this.$resultModal.setAttribute('data-visible-state', true); + } + + closeResultModal() { + this.$resultModal.setAttribute('data-visible-state', false); + } } export default LottoGameView; From 26dc565cfae45a979541947e5b3fcbc55c0cddaf Mon Sep 17 00:00:00 2001 From: "YongRae_Kim (Usage)" Date: Wed, 2 Mar 2022 21:55:49 +0900 Subject: [PATCH 07/23] =?UTF-8?q?feat:=20css=20=EC=9C=A0=EC=A0=80=20?= =?UTF-8?q?=ED=8E=B8=EC=9D=98=EC=84=B1=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 8 ++++++-- src/css/index.css | 31 +++++++++++++++++++++++++++++-- src/js/app.js | 16 ++++++---------- src/js/constants/selector.js | 2 ++ src/js/models/LottoGame.js | 2 +- src/js/views/index.js | 10 ++++++++++ 6 files changed, 54 insertions(+), 15 deletions(-) diff --git a/index.html b/index.html index a23df90cbc..8d5ba7df1e 100644 --- a/index.html +++ b/index.html @@ -18,7 +18,7 @@

    금액을 입력하는 섹션입니

    -
    +

    구매한 로또를 확인하는 섹션입니다.

    @@ -35,7 +35,11 @@

    구매한 로또를 확인하는 섹션입

    -
    +

    당첨 번호 입력 섹션

    지난 주 당첨번호 6개와 보너스 번호 1개를 입력해주세요. diff --git a/src/css/index.css b/src/css/index.css index b4cae8d43d..bcfdaf41c2 100644 --- a/src/css/index.css +++ b/src/css/index.css @@ -8,6 +8,10 @@ input { outline: none; } +label { + cursor: pointer; +} + body { width: 100vw; height: 100vh; @@ -60,13 +64,27 @@ button { font-weight: bold; } +button:hover { + cursor: pointer; + background-color: #26daf1; +} + section { margin-bottom: 20px; } -#lotto-section { +#lotto-section[data-visible-state='false'] { + display: flex; + visibility: hidden; + height: 0vh; +} + +#lotto-section[data-visible-state='true'] { display: flex; flex-direction: row; + height: 25vh; + visibility: visible; + transition: height 1s; } .lotto-wrapper { @@ -84,6 +102,7 @@ section { #lotto-container { display: flex; } + #lotto-container[data-visible-state='false'] { flex-direction: row; gap: 3px; @@ -103,8 +122,16 @@ section { gap: 10px; } -#win-number-input-section { +#win-number-input-section[data-visible-state='false'] { + visibility: hidden; + opacity: 0; + height: 0; +} + +#win-number-input-section[data-visible-state='true'] { margin-top: 40px; + opacity: 1; + transition: opacity 1s; } .win-number-input-notice { diff --git a/src/js/app.js b/src/js/app.js index 49c60e0f3b..71267fbd2c 100644 --- a/src/js/app.js +++ b/src/js/app.js @@ -25,20 +25,16 @@ class LottoGameManager { try { const { value: chargeInputStr } = this.$chargeInput; const chargeInput = Number(chargeInputStr); - this.triggerChargeInputAction(chargeInput); - } catch ({ message }) { + this.lottoGameModel.createLottoList(chargeInput); + + const lottoList = this.lottoGameModel.getLottoList(); + this.lottoGameView.renderLottoSection(lottoList); + this.lottoGameView.renderWinNumberInputSection(true); + } catch (message) { alert(message); } }; - triggerChargeInputAction(chargeInput) { - // mutate model - this.lottoGameModel.createLottoList(chargeInput); - // mutate view by new model state - const lottoList = this.lottoGameModel.getLottoList(); - this.lottoGameView.renderLottoSection(lottoList); - } - onChangeAlignState = (e) => { const { checked: alignState } = e.target; this.lottoGameView.renderAlignState(alignState); diff --git a/src/js/constants/selector.js b/src/js/constants/selector.js index 9ca43d8950..98968161ae 100644 --- a/src/js/constants/selector.js +++ b/src/js/constants/selector.js @@ -6,7 +6,9 @@ export const SELECTOR = { ALIGN_CONVERTER: '#align-converter', PURCHASED_MESSAGE: '#purchased-message', + LOTTO_SECTION: '#lotto-section', LOTTO_CONTAINER: '#lotto-container', + WIN_NUMBER_INPUT_SECTION: '#win-number-input-section', RESULT_MODAL: '#result-modal-area', EARNING_RATE_NOTICE: '#earning-rate-notice', diff --git a/src/js/models/LottoGame.js b/src/js/models/LottoGame.js index 995f6a2a68..db3535cf63 100644 --- a/src/js/models/LottoGame.js +++ b/src/js/models/LottoGame.js @@ -28,7 +28,7 @@ class LottoGameModel { }); this.lottoList = newLottoList; } catch ({ message }) { - alert(message); + throw message; } } diff --git a/src/js/views/index.js b/src/js/views/index.js index 04849ccf22..9a421c81f0 100644 --- a/src/js/views/index.js +++ b/src/js/views/index.js @@ -5,6 +5,8 @@ class LottoGameView { constructor() { this.$purchasedMessage = findElement(SELECTOR.PURCHASED_MESSAGE); this.$lottoContainer = findElement(SELECTOR.LOTTO_CONTAINER); + this.$lottoSection = findElement(SELECTOR.LOTTO_SECTION); + this.$winNumberInputSection = findElement(SELECTOR.WIN_NUMBER_INPUT_SECTION); this.$resultModal = findElement(SELECTOR.RESULT_MODAL); this.$earningRateNotice = findElement(SELECTOR.EARNING_RATE_NOTICE); this.$firstGradeAmount = findElement(SELECTOR.FIRST_GRADE_AMOUNT); @@ -17,9 +19,13 @@ class LottoGameView { initialize() { this.$purchasedMessage.innerText = ''; this.$lottoContainer.innerHTML = ''; + this.$lottoSection.setAttribute('data-visible-state', false); + this.renderWinNumberInputSection(false); + this.renderAlignState(false); } renderLottoSection(lottoList) { + this.$lottoSection.setAttribute('data-visible-state', true); this.$purchasedMessage.innerText = `총 ${lottoList.length}개를 구매하였습니다.`; this.$lottoContainer.innerHTML = lottoList .map((lotto) => this.generateLottoTemplate(lotto)) @@ -37,6 +43,10 @@ class LottoGameView { this.$lottoContainer.setAttribute('data-visible-state', visibleState); } + renderWinNumberInputSection(visibleState) { + this.$winNumberInputSection.setAttribute('data-visible-state', visibleState); + } + openResultModal(resultArray) { this.$firstGradeAmount.innerText = `${resultArray[0]}개`; this.$secondGradeAmount.innerText = `${resultArray[1]}개`; From d34d36644f27090dd3065e4e4f9598810d4dfa15 Mon Sep 17 00:00:00 2001 From: "YongRae_Kim (Usage)" Date: Thu, 3 Mar 2022 23:37:21 +0900 Subject: [PATCH 08/23] =?UTF-8?q?feat:=20=EB=8B=B9=EC=B2=A8=20=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EC=9C=A0=ED=9A=A8=EC=84=B1=20=EA=B2=80=EC=82=AC=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/js/app.js | 16 ++++++++++++---- src/js/constants/errorMessage.js | 2 ++ src/js/models/LottoGame.js | 27 ++++++++++++++++++--------- src/js/utils/validator.js | 5 +++++ 4 files changed, 37 insertions(+), 13 deletions(-) diff --git a/src/js/app.js b/src/js/app.js index 71267fbd2c..f2dcb3e381 100644 --- a/src/js/app.js +++ b/src/js/app.js @@ -42,7 +42,17 @@ class LottoGameManager { onSubmitWinNumberInputForm = (e) => { e.preventDefault(); - const inputWinNumber = [ + try { + const inputWinNumber = this.getInputWinNumber(e); + const gameResult = this.lottoGameModel.getGameResult(inputWinNumber); + this.lottoGameView.openResultModal(gameResult); + } catch (message) { + alert(message); + } + }; + + getInputWinNumber(e) { + return [ Number(e.path[0][0].value), Number(e.path[0][1].value), Number(e.path[0][2].value), @@ -51,9 +61,7 @@ class LottoGameManager { Number(e.path[0][5].value), Number(e.path[0][6].value), ]; - const gameResult = this.lottoGameModel.getGameResult(inputWinNumber); - this.lottoGameView.openResultModal(gameResult); - }; + } onClickReplayButton = () => { this.lottoGameModel.initialize(); diff --git a/src/js/constants/errorMessage.js b/src/js/constants/errorMessage.js index f12977bb92..a1e9df1775 100644 --- a/src/js/constants/errorMessage.js +++ b/src/js/constants/errorMessage.js @@ -1,4 +1,6 @@ export const ERROR_MESSAGE = { CHARGE_IS_INVALIDATE: '금액은 1000원 이상이어야합니다. 금액을 다시 입력해주세요.', LOTTO_NUMBER_IS_INVALIDATE: '로또 숫자들의 값이 부정확합니다. 금액을 다시 입력해주세요.', + WIN_NUMBER_IS_INVALIDATE: '당첨 숫자의 범위는 1에서 45사이 입니다. 다시 입력해주세요.', + DUPLICATE_NUMBER_IS_EXIST: '중복된 숫자가 포함되어 있습니다. 다시 입력해주세요.', }; diff --git a/src/js/models/LottoGame.js b/src/js/models/LottoGame.js index db3535cf63..d22f35313e 100644 --- a/src/js/models/LottoGame.js +++ b/src/js/models/LottoGame.js @@ -1,5 +1,10 @@ import Lotto from './Lotto'; -import { isValidCharge, getRandomNumber } from '../utils/validator'; +import { + isValidNumber, + isValidCharge, + getRandomNumber, + hasUniqueElement, +} from '../utils/validator'; import { ERROR_MESSAGE } from '../constants/errorMessage'; import { NUMBER } from '../constants/number'; @@ -14,12 +19,10 @@ class LottoGameModel { } getLottoList() { - /** getter로 가져간 lottoList를 변경하여도 lottoList의 멤버에겐 영향이 없다. */ return this.lottoList.deepCopy(); } createLottoList(chargeInput) { - /** 정상적이지 않은 로또가 하나라도 존재한다면, 멤버는 빈 값이고 사용자는 금액을 다시 입력하여야 한다. */ try { const availableLottoAmount = this.exchangeChargeToLottoAmount(chargeInput); const newLottoList = new Array(availableLottoAmount).fill().map(() => { @@ -50,12 +53,18 @@ class LottoGameModel { } getGameResult(winningNumbers) { - this.winningResult = [0, 0, 0, 0, 0, 0, 0]; - this.lottoList.forEach((lotto) => { - this.updateLottoRankResult(lotto, winningNumbers); - }); - this.updateLottoEarningRate(); - return this.winningResult; + if (isValidNumber(winningNumbers)) { + if (hasUniqueElement(winningNumbers)) { + this.winningResult = [0, 0, 0, 0, 0, 0, 0]; + this.lottoList.forEach((lotto) => { + this.updateLottoRankResult(lotto, winningNumbers); + }); + this.updateLottoEarningRate(); + return this.winningResult; + } + throw new Error(ERROR_MESSAGE.DUPLICATE_NUMBER_IS_EXIST); + } + throw new Error(ERROR_MESSAGE.WIN_NUMBER_IS_INVALIDATE); } updateLottoRankResult(lotto, winningNumbers) { diff --git a/src/js/utils/validator.js b/src/js/utils/validator.js index 60038cbd19..67f6b0d677 100644 --- a/src/js/utils/validator.js +++ b/src/js/utils/validator.js @@ -27,3 +27,8 @@ export function getRandomNumber(array) { return randomNumber; } + +export function hasUniqueElement(element) { + const uniqueSet = new Set(element); + return uniqueSet.size === element.length; +} From b64913d184a17ec9372f36393214729e6abd26c9 Mon Sep 17 00:00:00 2001 From: "YongRae_Kim (Usage)" Date: Fri, 4 Mar 2022 01:40:05 +0900 Subject: [PATCH 09/23] =?UTF-8?q?feat:=20=EB=A1=9C=EB=98=90=20=EC=BB=A8?= =?UTF-8?q?=ED=85=8C=EC=9D=B4=EB=84=88=EC=9D=98=20=EB=86=92=EC=9D=B4=20?= =?UTF-8?q?=EA=B0=92=EC=9D=B4=20=EB=8A=98=EC=96=B4=EB=82=A0=20=EA=B2=BD?= =?UTF-8?q?=EC=9A=B0=20=EC=95=A0=EB=8B=88=EB=A9=94=EC=9D=B4=EC=85=98=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/css/index.css | 22 ++++++++++++++-------- src/js/app.js | 2 +- src/js/views/index.js | 12 ++++++++++-- 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/src/css/index.css b/src/css/index.css index bcfdaf41c2..54355219ac 100644 --- a/src/css/index.css +++ b/src/css/index.css @@ -4,8 +4,9 @@ input[type='number']::-webkit-inner-spin-button { margin: 0; } -input { - outline: none; +input:focus { + border: 1px solid #00bcd4; + outline: 2px solid #00bcd4; } label { @@ -13,16 +14,16 @@ label { } body { - width: 100vw; - height: 100vh; - margin: auto; + width: 100%; + min-height: 100vh; + margin: 0; background-color: rgba(0, 0, 0, 0.07); font-family: 'NanumBarunGothic', sans-serif; font-size: 1.1rem; - display: flex; justify-content: center; align-items: center; + overflow: overlay; } #app { @@ -82,9 +83,9 @@ section { #lotto-section[data-visible-state='true'] { display: flex; flex-direction: row; - height: 25vh; + height: 27vh; visibility: visible; - transition: height 1s; + transition: height 0.5s; } .lotto-wrapper { @@ -101,6 +102,7 @@ section { #lotto-container { display: flex; + flex-wrap: wrap; } #lotto-container[data-visible-state='false'] { @@ -144,6 +146,10 @@ section { justify-content: space-between; } +.win-number-input-wrapper > div > input { + text-align: center; +} + #result-button { width: 100%; margin-top: 10px; diff --git a/src/js/app.js b/src/js/app.js index f2dcb3e381..dc5692e01d 100644 --- a/src/js/app.js +++ b/src/js/app.js @@ -37,7 +37,7 @@ class LottoGameManager { onChangeAlignState = (e) => { const { checked: alignState } = e.target; - this.lottoGameView.renderAlignState(alignState); + this.lottoGameView.renderAlignState(alignState, this.lottoGameModel.getLottoList().length); }; onSubmitWinNumberInputForm = (e) => { diff --git a/src/js/views/index.js b/src/js/views/index.js index 9a421c81f0..835c2fe84b 100644 --- a/src/js/views/index.js +++ b/src/js/views/index.js @@ -39,8 +39,16 @@ class LottoGameView { `; } - renderAlignState(visibleState) { - this.$lottoContainer.setAttribute('data-visible-state', visibleState); + renderAlignState(visibleState, lottoAmount = 0) { + if (visibleState) { + this.$lottoSection.style.height = `${lottoAmount * 46.364}px`; + setTimeout(() => { + this.$lottoContainer.setAttribute('data-visible-state', visibleState); + }, 500); + } else { + this.$lottoContainer.setAttribute('data-visible-state', visibleState); + this.$lottoSection.style.height = `27vh`; + } } renderWinNumberInputSection(visibleState) { From cc065f2b59cff94ec52d8b32f166a97854b25d52 Mon Sep 17 00:00:00 2001 From: "YongRae_Kim (Usage)" Date: Fri, 4 Mar 2022 22:49:53 +0900 Subject: [PATCH 10/23] =?UTF-8?q?fix:=20=EC=95=A0=EB=8B=88=EB=A9=94?= =?UTF-8?q?=EC=9D=B4=EC=85=98=EC=A4=91=20=ED=81=B4=EB=A6=AD=EC=8B=9C=20?= =?UTF-8?q?=EB=B2=84=EA=B7=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/css/index.css | 2 +- src/js/constants/elementProperty.js | 4 +++ src/js/constants/number.js | 4 +++ src/js/views/index.js | 40 ++++++++++++++++++++++++----- 4 files changed, 43 insertions(+), 7 deletions(-) create mode 100644 src/js/constants/elementProperty.js diff --git a/src/css/index.css b/src/css/index.css index 54355219ac..da08ec1a70 100644 --- a/src/css/index.css +++ b/src/css/index.css @@ -83,7 +83,7 @@ section { #lotto-section[data-visible-state='true'] { display: flex; flex-direction: row; - height: 27vh; + height: 237.84px; visibility: visible; transition: height 0.5s; } diff --git a/src/js/constants/elementProperty.js b/src/js/constants/elementProperty.js new file mode 100644 index 0000000000..bdb089ed44 --- /dev/null +++ b/src/js/constants/elementProperty.js @@ -0,0 +1,4 @@ +export const ELEMENT_PROPERTY = { + HEIGHT_OF_ONE_LOTTO_ICON_LINE: 46.364, + DEFAULT_HEIGHT_OF_LOTTO_SECTION: 237.84, +}; diff --git a/src/js/constants/number.js b/src/js/constants/number.js index cad578ffad..e98103d5e9 100644 --- a/src/js/constants/number.js +++ b/src/js/constants/number.js @@ -16,4 +16,8 @@ export const NUMBER = { FIFTH_GRADE_INDEX: 4, EARNING_RATE_INDEX: 5, NOT_WINNING_INDEX: 6, + LOTTO_ELEMENT_PER_LINE: 7, + LOTTO_SECTIONS_DEFALUT_CAPACITY_IN_ICON: 35, + LOTTO_SECTIONS_DEFALUT_CAPACITY_IN_DETAIL: 5, + ANIMATION_TIME: 500, }; diff --git a/src/js/views/index.js b/src/js/views/index.js index 835c2fe84b..fbc167b45e 100644 --- a/src/js/views/index.js +++ b/src/js/views/index.js @@ -1,5 +1,7 @@ import { SELECTOR } from '../constants/selector'; import { findElement } from '../utils/elementSelector'; +import { ELEMENT_PROPERTY } from '../constants/elementProperty'; +import { NUMBER } from '../constants/number'; class LottoGameView { constructor() { @@ -14,6 +16,7 @@ class LottoGameView { this.$thirdGradeAmount = findElement(SELECTOR.THIRD_GRADE_AMOUNT); this.$fourthGradeAmount = findElement(SELECTOR.FOURTH_GRADE_AMOUNT); this.$fifthGradeAmount = findElement(SELECTOR.FIFTH_GRADE_AMOUNT); + this.$alignConverter = findElement(SELECTOR.ALIGN_CONVERTER); } initialize() { @@ -39,16 +42,41 @@ class LottoGameView { `; } + // 내부 구현이 너무 길어져서 메서드를 분리 renderAlignState(visibleState, lottoAmount = 0) { if (visibleState) { - this.$lottoSection.style.height = `${lottoAmount * 46.364}px`; - setTimeout(() => { - this.$lottoContainer.setAttribute('data-visible-state', visibleState); - }, 500); - } else { + if (lottoAmount > NUMBER.LOTTO_SECTIONS_DEFALUT_CAPACITY_IN_DETAIL) { + this.$lottoSection.style.height = this.#calculateVisibleLottoSectionHeight(lottoAmount); + this.$alignConverter.setAttribute('disabled', true); + setTimeout(() => { + this.$lottoContainer.setAttribute('data-visible-state', visibleState); + this.$alignConverter.removeAttribute('disabled'); + }, NUMBER.ANIMATION_TIME); + return; + } this.$lottoContainer.setAttribute('data-visible-state', visibleState); - this.$lottoSection.style.height = `27vh`; + return; } + this.$lottoContainer.setAttribute('data-visible-state', visibleState); + this.$lottoSection.style.height = this.#calculateInvisibleLottoSectionHeight(lottoAmount); + } + + #calculateVisibleLottoSectionHeight(lottoAmount) { + return `${lottoAmount * ELEMENT_PROPERTY.HEIGHT_OF_ONE_LOTTO_ICON_LINE}px`; + } + + #calculateInvisibleLottoSectionHeight(lottoAmount) { + if (lottoAmount > NUMBER.LOTTO_SECTIONS_DEFALUT_CAPACITY_IN_ICON) { + const linesOfLottoIcon = Math.ceil( + (lottoAmount - NUMBER.LOTTO_SECTIONS_DEFALUT_CAPACITY_IN_ICON) / + NUMBER.LOTTO_ELEMENT_PER_LINE + ); + return `${ + linesOfLottoIcon * ELEMENT_PROPERTY.HEIGHT_OF_ONE_LOTTO_ICON_LINE + + ELEMENT_PROPERTY.DEFAULT_HEIGHT_OF_LOTTO_SECTION + }px`; + } + return `${ELEMENT_PROPERTY.DEFAULT_HEIGHT_OF_LOTTO_SECTION}px`; } renderWinNumberInputSection(visibleState) { From bdeff9f3c89084d131849f8e5026a6e4d73d4d9d Mon Sep 17 00:00:00 2001 From: "YongRae_Kim (Usage)" Date: Sat, 5 Mar 2022 00:00:51 +0900 Subject: [PATCH 11/23] =?UTF-8?q?feat:=20=EB=8B=B9=EC=B2=A8=20=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EC=9C=A0=ED=9A=A8=EC=84=B1=20=EA=B2=80=EC=82=AC=20?= =?UTF-8?q?=EB=B0=8F=20=EB=8B=A4=EC=9D=8C=20=EB=B2=88=ED=98=B8=20=EC=9E=90?= =?UTF-8?q?=EB=8F=99=20=ED=8F=AC=EC=BB=A4=EC=8B=B1=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .eslintrc.js | 3 ++- index.html | 14 +++++------ src/css/index.css | 10 ++++++++ src/css/modal.css | 2 +- src/js/__tests__/lottoGame.test.js | 2 +- src/js/app.js | 39 +++++++++++++++++++++++------ src/js/constants/elementProperty.js | 1 + src/js/constants/selector.js | 3 ++- src/js/models/LottoGame.js | 4 ++- src/js/utils/validator.js | 4 +++ src/js/views/index.js | 14 ++++++++++- 11 files changed, 75 insertions(+), 21 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 6682b83093..96400bec4a 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -14,7 +14,7 @@ module.exports = { rules: { 'no-var': 'error', 'max-depth': ['error', 2], - 'max-lines-per-function': ['error', 15], + 'max-lines-per-function': ['error', 20], 'no-console': 'warn', 'no-param-reassign': 'error', 'padding-line-between-statements': 0, @@ -22,5 +22,6 @@ module.exports = { 'no-undefined': 0, 'no-constant-condition': 0, 'no-unused-private-class-members': 0, + 'lines-between-class-members': 0, }, }; diff --git a/index.html b/index.html index 8d5ba7df1e..a517a43b63 100644 --- a/index.html +++ b/index.html @@ -48,17 +48,17 @@

    당첨 번호 입력 섹션

    당첨 번호

    - - - - - - + + + + + +

    보너스 번호

    - +
    diff --git a/src/css/index.css b/src/css/index.css index da08ec1a70..d5b1b9ae63 100644 --- a/src/css/index.css +++ b/src/css/index.css @@ -9,6 +9,16 @@ input:focus { outline: 2px solid #00bcd4; } +input[data-invalid-state='true'] { + background-color: #ffb0cd; + border: 1px solid #ff6464; + outline: 2px solid #ff6464; +} + +input[data-invalid-state='false'] { + background-color: #ffffff; +} + label { cursor: pointer; } diff --git a/src/css/modal.css b/src/css/modal.css index 2bc92887aa..09e7b94495 100644 --- a/src/css/modal.css +++ b/src/css/modal.css @@ -5,7 +5,7 @@ #result-modal-area[data-visible-state='true'] { width: 100vw; height: 100vh; - position: absolute; + position: fixed; left: 0; top: 0; } diff --git a/src/js/__tests__/lottoGame.test.js b/src/js/__tests__/lottoGame.test.js index b88dccc6e3..0b73322f2d 100644 --- a/src/js/__tests__/lottoGame.test.js +++ b/src/js/__tests__/lottoGame.test.js @@ -48,7 +48,7 @@ describe('로또 게임 모델 테스트', () => { const lottoGame = new LottoGame(); const lottoList = []; const winningNumbers = [1, 2, 3, 4, 5, 6, 10]; - const result = [1, 0, 1, 1, 0, 667183, 0]; + const result = [1, 0, 1, 1, 0, 66718300, 0]; lottoList.push(Lotto.create([1, 2, 3, 4, 5, 6])); lottoList.push(Lotto.create([1, 2, 3, 4, 5, 7])); diff --git a/src/js/app.js b/src/js/app.js index dc5692e01d..0ecd4c3613 100644 --- a/src/js/app.js +++ b/src/js/app.js @@ -2,20 +2,25 @@ import LottoGameModel from './models/LottoGame'; import { SELECTOR } from './constants/selector'; import LottoGameView from './views'; import { findElement } from './utils/elementSelector'; +import { isNotValidNumber } from './utils/validator'; class LottoGameManager { + lottoGameModel = new LottoGameModel(); + lottoGameView = new LottoGameView(); + $chargeForm = findElement(SELECTOR.CHARGE_INPUT_FORM); + $chargeInput = findElement(SELECTOR.CHARGE_INPUT); + $alignConverter = findElement(SELECTOR.ALIGN_CONVERTER); + $winNumberForm = findElement(SELECTOR.WIN_NUMBER_INPUT_FORM); + $modalCloseButton = findElement(SELECTOR.MODAL_CLOSE_BUTTON); + $replayButton = findElement(SELECTOR.REPLAY_BUTTON); + $lastWinNumberInput = findElement(SELECTOR.LAST_WIN_NUMBER_INPUT); + $bonusNumberInput = findElement(SELECTOR.BONUS_NUMBER_INPUT); + init() { - this.lottoGameModel = new LottoGameModel(); - this.lottoGameView = new LottoGameView(); - this.$chargeForm = findElement(SELECTOR.CHARGE_INPUT_FORM); - this.$chargeInput = findElement(SELECTOR.CHARGE_INPUT); - this.$alignConverter = findElement(SELECTOR.ALIGN_CONVERTER); - this.$winNumberForm = findElement(SELECTOR.WIN_NUMBER_INPUT_FORM); - this.$modalCloseButton = findElement(SELECTOR.MODAL_CLOSE_BUTTON); - this.$replayButton = findElement(SELECTOR.REPLAY_BUTTON); this.$chargeForm.addEventListener('submit', this.onSubmitChargeInputForm); this.$alignConverter.addEventListener('change', this.onChangeAlignState); this.$winNumberForm.addEventListener('submit', this.onSubmitWinNumberInputForm); + this.$winNumberForm.addEventListener('input', this.onInputWinNumberForm); this.$replayButton.addEventListener('click', this.onClickReplayButton); this.$modalCloseButton.addEventListener('click', this.onClickCloseModalButton); } @@ -40,6 +45,24 @@ class LottoGameManager { this.lottoGameView.renderAlignState(alignState, this.lottoGameModel.getLottoList().length); }; + onInputWinNumberForm = (e) => { + if (isNotValidNumber(Number(e.target.value))) { + this.lottoGameView.setInvalidInputState(e.target); + e.target.value = ''; + return; + } + this.lottoGameView.setValidInputState(e.target); + if (e.target.value.length === 2) { + if (e.target.nextElementSibling !== null) { + e.target.nextElementSibling.focus(); + return; + } + if (e.target === this.$lastWinNumberInput) { + this.$bonusNumberInput.focus(); + } + } + }; + onSubmitWinNumberInputForm = (e) => { e.preventDefault(); try { diff --git a/src/js/constants/elementProperty.js b/src/js/constants/elementProperty.js index bdb089ed44..c0473de65e 100644 --- a/src/js/constants/elementProperty.js +++ b/src/js/constants/elementProperty.js @@ -1,4 +1,5 @@ export const ELEMENT_PROPERTY = { HEIGHT_OF_ONE_LOTTO_ICON_LINE: 46.364, + GAP_OF_LOTTO_ITEM: 3, DEFAULT_HEIGHT_OF_LOTTO_SECTION: 237.84, }; diff --git a/src/js/constants/selector.js b/src/js/constants/selector.js index 98968161ae..25d800deaf 100644 --- a/src/js/constants/selector.js +++ b/src/js/constants/selector.js @@ -2,7 +2,8 @@ export const SELECTOR = { CHARGE_INPUT_FORM: '#charge-input-form', CHARGE_INPUT: '#charge-input', WIN_NUMBER_INPUT_FORM: '#win-number-input-form', - WIN_NUMBER_INPUT: '#win-number-', + LAST_WIN_NUMBER_INPUT: '#win-number-6', + BONUS_NUMBER_INPUT: '#bonus-number', ALIGN_CONVERTER: '#align-converter', PURCHASED_MESSAGE: '#purchased-message', diff --git a/src/js/models/LottoGame.js b/src/js/models/LottoGame.js index d22f35313e..d55067bc0d 100644 --- a/src/js/models/LottoGame.js +++ b/src/js/models/LottoGame.js @@ -79,7 +79,9 @@ class LottoGameModel { NUMBER.THIRD_GRADE_PRIZE * this.winningResult[NUMBER.THIRD_GRADE_INDEX] + NUMBER.FOURTH_GRADE_PRIZE * this.winningResult[NUMBER.FOURTH_GRADE_INDEX] + NUMBER.FIFTH_GRADE_PRIZE * this.winningResult[NUMBER.FIFTH_GRADE_INDEX]; - this.winningResult[NUMBER.EARNING_RATE_INDEX] = Math.floor(totalWinningMoney / totalCharge); + this.winningResult[NUMBER.EARNING_RATE_INDEX] = Math.floor( + (totalWinningMoney / totalCharge) * 100 + ); } } diff --git a/src/js/utils/validator.js b/src/js/utils/validator.js index 67f6b0d677..ac33b41068 100644 --- a/src/js/utils/validator.js +++ b/src/js/utils/validator.js @@ -13,6 +13,10 @@ export function isValidNumber(lottoNumbers) { ); } +export function isNotValidNumber(number) { + return number < 1 || number > 45; +} + export function isValidCharge(charge) { return Number.isInteger(charge) && charge >= NUMBER.LOTTO_PRICE; } diff --git a/src/js/views/index.js b/src/js/views/index.js index fbc167b45e..92d8cd3a2a 100644 --- a/src/js/views/index.js +++ b/src/js/views/index.js @@ -22,9 +22,11 @@ class LottoGameView { initialize() { this.$purchasedMessage.innerText = ''; this.$lottoContainer.innerHTML = ''; + this.$alignConverter.checked = false; this.$lottoSection.setAttribute('data-visible-state', false); this.renderWinNumberInputSection(false); this.renderAlignState(false); + this.$lottoSection.style.height = 0; } renderLottoSection(lottoList) { @@ -33,6 +35,7 @@ class LottoGameView { this.$lottoContainer.innerHTML = lottoList .map((lotto) => this.generateLottoTemplate(lotto)) .join(''); + this.$lottoSection.style.height = this.#calculateInvisibleLottoSectionHeight(lottoList.length); } generateLottoTemplate({ lottoNumbers }) { @@ -72,7 +75,8 @@ class LottoGameView { NUMBER.LOTTO_ELEMENT_PER_LINE ); return `${ - linesOfLottoIcon * ELEMENT_PROPERTY.HEIGHT_OF_ONE_LOTTO_ICON_LINE + + linesOfLottoIcon * + (ELEMENT_PROPERTY.HEIGHT_OF_ONE_LOTTO_ICON_LINE + ELEMENT_PROPERTY.GAP_OF_LOTTO_ITEM) + ELEMENT_PROPERTY.DEFAULT_HEIGHT_OF_LOTTO_SECTION }px`; } @@ -83,6 +87,14 @@ class LottoGameView { this.$winNumberInputSection.setAttribute('data-visible-state', visibleState); } + setInvalidInputState(target) { + target.setAttribute('data-invalid-state', true); + } + + setValidInputState(target) { + target.setAttribute('data-invalid-state', false); + } + openResultModal(resultArray) { this.$firstGradeAmount.innerText = `${resultArray[0]}개`; this.$secondGradeAmount.innerText = `${resultArray[1]}개`; From cb33016980d358c0e63200d113641ae850dc67c0 Mon Sep 17 00:00:00 2001 From: "YongRae_Kim (Usage)" Date: Sat, 5 Mar 2022 00:10:16 +0900 Subject: [PATCH 12/23] =?UTF-8?q?refactor:=20LottoGame.js=20->=20LottoRoun?= =?UTF-8?q?d.js=20=ED=8C=8C=EC=9D=BC=20=EC=9D=B4=EB=A6=84=20=EB=B0=8F=20?= =?UTF-8?q?=EB=A9=94=EC=86=8C=EB=93=9C=20=EC=9D=B4=EB=A6=84=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/js/__tests__/lottoGame.test.js | 44 +++++++++---------- src/js/app.js | 38 ++++++++-------- src/js/models/{LottoGame.js => LottoRound.js} | 6 +-- src/js/views/index.js | 4 +- 4 files changed, 46 insertions(+), 46 deletions(-) rename src/js/models/{LottoGame.js => LottoRound.js} (96%) diff --git a/src/js/__tests__/lottoGame.test.js b/src/js/__tests__/lottoGame.test.js index 0b73322f2d..31fcd6cea5 100644 --- a/src/js/__tests__/lottoGame.test.js +++ b/src/js/__tests__/lottoGame.test.js @@ -3,68 +3,68 @@ import '../utils/customPrototypeMethod'; import { ERROR_MESSAGE } from '../constants/errorMessage'; -import LottoGame from '../models/LottoGame'; +import LottoRound from '../models/LottoRound'; import Lotto from '../models/Lotto'; const charge = 5000; describe('로또 게임 모델 테스트', () => { it('로또 게임 모델에 금액이 정상적으로 입력되면, 구매할 수 있는 로또의 수를 반환할 수 있어야 한다.', () => { - const lottoGame = new LottoGame(); + const lottoRound = new LottoRound(); const expectedAvailableLottoAmount = 5; - const availableLottoAmount = lottoGame.exchangeChargeToLottoAmount(charge); + const availableLottoAmount = lottoRound.exchangeChargeToLottoAmount(charge); expect(availableLottoAmount).toBe(expectedAvailableLottoAmount); }); it('금액은 1000이상의 숫자여야한다.', () => { - const lottoGame = new LottoGame(); + const lottoRound = new LottoRound(); const lessThanLottoPriceCharge = 500; try { - lottoGame.exchangeChargeToLottoAmount(lessThanLottoPriceCharge); + lottoRound.exchangeChargeToLottoAmount(lessThanLottoPriceCharge); } catch ({ message }) { expect(message).toEqual(ERROR_MESSAGE.CHARGE_IS_INVALIDATE); } }); it('로또 번호 배열들을 입력하여 로또 모델을 생성하고 관리할 수 있어야 한다.', () => { - const lottoGame = new LottoGame(); - const availableLottoAmount = lottoGame.exchangeChargeToLottoAmount(charge); + const lottoRound = new LottoRound(); + const availableLottoAmount = lottoRound.exchangeChargeToLottoAmount(charge); - lottoGame.createLottoList(charge); + lottoRound.createLottoList(charge); - expect(lottoGame.lottoList.length).toBe(availableLottoAmount); + expect(lottoRound.lottoList.length).toBe(availableLottoAmount); }); it('lottoList의 getter는 깊게 복사된 값을 반환한다.', () => { - const lottoGame = new LottoGame(); + const lottoRound = new LottoRound(); - lottoGame.createLottoList(charge); + lottoRound.createLottoList(charge); - const lottoListFromGetterFunc = lottoGame.getLottoList(); - expect(lottoListFromGetterFunc).toEqual(lottoGame.lottoList); + const lottoListFromGetterFunc = lottoRound.getLottoList(); + expect(lottoListFromGetterFunc).toEqual(lottoRound.lottoList); }); it('당첨 결과를 이용하여 당첨 통계와 수익률을 반환할 수 있어야 한다.', () => { - const lottoGame = new LottoGame(); + const lottoRound = new LottoRound(); const lottoList = []; const winningNumbers = [1, 2, 3, 4, 5, 6, 10]; - const result = [1, 0, 1, 1, 0, 66718300, 0]; + const result = [1, 0, 1, 1, 0, 66718333, 0]; lottoList.push(Lotto.create([1, 2, 3, 4, 5, 6])); lottoList.push(Lotto.create([1, 2, 3, 4, 5, 7])); lottoList.push(Lotto.create([1, 2, 3, 4, 7, 8])); - lottoGame.lottoList = lottoList; - expect(lottoGame.getGameResult(winningNumbers)).toEqual(result); + lottoRound.lottoList = lottoList; + expect(lottoRound.getRoundResult(winningNumbers)).toEqual(result); }); it('게임 초기화가 가능해야 한다.', () => { - const lottoGame = new LottoGame(); - const initializedLottoGame = new LottoGame(); + const lottoRound = new LottoRound(); + const initializedLottoRound = new LottoRound(); - lottoGame.createLottoList(charge); - lottoGame.initialize(); + lottoRound.createLottoList(charge); + lottoRound.initialize(); - expect(lottoGame).toEqual(initializedLottoGame); + expect(lottoRound).toEqual(initializedLottoRound); }); }); diff --git a/src/js/app.js b/src/js/app.js index 0ecd4c3613..5a8dd8e7a2 100644 --- a/src/js/app.js +++ b/src/js/app.js @@ -1,12 +1,12 @@ -import LottoGameModel from './models/LottoGame'; +import LottoRoundModel from './models/LottoRound'; import { SELECTOR } from './constants/selector'; -import LottoGameView from './views'; +import LottoRoundView from './views'; import { findElement } from './utils/elementSelector'; import { isNotValidNumber } from './utils/validator'; -class LottoGameManager { - lottoGameModel = new LottoGameModel(); - lottoGameView = new LottoGameView(); +class LottoRoundManager { + lottoRoundModel = new LottoRoundModel(); + lottoRoundView = new LottoRoundView(); $chargeForm = findElement(SELECTOR.CHARGE_INPUT_FORM); $chargeInput = findElement(SELECTOR.CHARGE_INPUT); $alignConverter = findElement(SELECTOR.ALIGN_CONVERTER); @@ -30,11 +30,11 @@ class LottoGameManager { try { const { value: chargeInputStr } = this.$chargeInput; const chargeInput = Number(chargeInputStr); - this.lottoGameModel.createLottoList(chargeInput); + this.lottoRoundModel.createLottoList(chargeInput); - const lottoList = this.lottoGameModel.getLottoList(); - this.lottoGameView.renderLottoSection(lottoList); - this.lottoGameView.renderWinNumberInputSection(true); + const lottoList = this.lottoRoundModel.getLottoList(); + this.lottoRoundView.renderLottoSection(lottoList); + this.lottoRoundView.renderWinNumberInputSection(true); } catch (message) { alert(message); } @@ -42,16 +42,16 @@ class LottoGameManager { onChangeAlignState = (e) => { const { checked: alignState } = e.target; - this.lottoGameView.renderAlignState(alignState, this.lottoGameModel.getLottoList().length); + this.lottoRoundView.renderAlignState(alignState, this.lottoRoundModel.getLottoList().length); }; onInputWinNumberForm = (e) => { if (isNotValidNumber(Number(e.target.value))) { - this.lottoGameView.setInvalidInputState(e.target); + this.lottoRoundView.setInvalidInputState(e.target); e.target.value = ''; return; } - this.lottoGameView.setValidInputState(e.target); + this.lottoRoundView.setValidInputState(e.target); if (e.target.value.length === 2) { if (e.target.nextElementSibling !== null) { e.target.nextElementSibling.focus(); @@ -67,8 +67,8 @@ class LottoGameManager { e.preventDefault(); try { const inputWinNumber = this.getInputWinNumber(e); - const gameResult = this.lottoGameModel.getGameResult(inputWinNumber); - this.lottoGameView.openResultModal(gameResult); + const roundResult = this.lottoRoundModel.getRoundResult(inputWinNumber); + this.lottoRoundView.openResultModal(roundResult); } catch (message) { alert(message); } @@ -87,15 +87,15 @@ class LottoGameManager { } onClickReplayButton = () => { - this.lottoGameModel.initialize(); - this.lottoGameView.initialize(); + this.lottoRoundModel.initialize(); + this.lottoRoundView.initialize(); this.$chargeForm.reset(); this.$winNumberForm.reset(); - this.lottoGameView.closeResultModal(); + this.lottoRoundView.closeResultModal(); }; onClickCloseModalButton = () => { - this.lottoGameView.closeResultModal(); + this.lottoRoundView.closeResultModal(); }; } -export default LottoGameManager; +export default LottoRoundManager; diff --git a/src/js/models/LottoGame.js b/src/js/models/LottoRound.js similarity index 96% rename from src/js/models/LottoGame.js rename to src/js/models/LottoRound.js index d55067bc0d..5d1470dd4b 100644 --- a/src/js/models/LottoGame.js +++ b/src/js/models/LottoRound.js @@ -8,7 +8,7 @@ import { import { ERROR_MESSAGE } from '../constants/errorMessage'; import { NUMBER } from '../constants/number'; -class LottoGameModel { +class LottoRoundModel { constructor() { this.initialize(); } @@ -52,7 +52,7 @@ class LottoGameModel { throw new Error(ERROR_MESSAGE.CHARGE_IS_INVALIDATE); } - getGameResult(winningNumbers) { + getRoundResult(winningNumbers) { if (isValidNumber(winningNumbers)) { if (hasUniqueElement(winningNumbers)) { this.winningResult = [0, 0, 0, 0, 0, 0, 0]; @@ -85,4 +85,4 @@ class LottoGameModel { } } -export default LottoGameModel; +export default LottoRoundModel; diff --git a/src/js/views/index.js b/src/js/views/index.js index 92d8cd3a2a..980fddc42b 100644 --- a/src/js/views/index.js +++ b/src/js/views/index.js @@ -3,7 +3,7 @@ import { findElement } from '../utils/elementSelector'; import { ELEMENT_PROPERTY } from '../constants/elementProperty'; import { NUMBER } from '../constants/number'; -class LottoGameView { +class LottoRoundView { constructor() { this.$purchasedMessage = findElement(SELECTOR.PURCHASED_MESSAGE); this.$lottoContainer = findElement(SELECTOR.LOTTO_CONTAINER); @@ -110,4 +110,4 @@ class LottoGameView { this.$resultModal.setAttribute('data-visible-state', false); } } -export default LottoGameView; +export default LottoRoundView; From 47df9c73250fe547af8218ccbf96d240ae818111 Mon Sep 17 00:00:00 2001 From: "YongRae_Kim (Usage)" Date: Sun, 6 Mar 2022 13:16:42 +0900 Subject: [PATCH 13/23] =?UTF-8?q?chore:=20=EC=A4=91=EB=B3=B5=EB=90=98?= =?UTF-8?q?=EB=8A=94=20css=20=ED=95=A0=EB=8B=B9=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/css/index.css | 1 - 1 file changed, 1 deletion(-) diff --git a/src/css/index.css b/src/css/index.css index d5b1b9ae63..becd7cbff9 100644 --- a/src/css/index.css +++ b/src/css/index.css @@ -93,7 +93,6 @@ section { #lotto-section[data-visible-state='true'] { display: flex; flex-direction: row; - height: 237.84px; visibility: visible; transition: height 0.5s; } From c88a7999719026dabd85ffe140de640881bf3a74 Mon Sep 17 00:00:00 2001 From: "YongRae_Kim (Usage)" Date: Sun, 6 Mar 2022 13:37:26 +0900 Subject: [PATCH 14/23] =?UTF-8?q?test:=20=EB=A1=9C=EB=98=90=20=EB=AA=A8?= =?UTF-8?q?=EB=8D=B8=20=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BC=80=EC=9D=B4?= =?UTF-8?q?=EC=8A=A4=20=EB=B3=B4=EC=99=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/js/__tests__/lotto.test.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/js/__tests__/lotto.test.js b/src/js/__tests__/lotto.test.js index 9a8c6fdb78..0092aebcd9 100644 --- a/src/js/__tests__/lotto.test.js +++ b/src/js/__tests__/lotto.test.js @@ -22,9 +22,13 @@ describe('로또 모델 테스트', () => { it('로또 모델의 번호와 당첨 번호를 비교하여 등수를 반환할 수 있어야 한다.', () => { const lottoNumbers = [1, 2, 3, 4, 5, 6]; - const winningNumbers = [1, 2, 3, 4, 5, 7, 6]; + const winningFirstNumbers = [1, 2, 3, 4, 5, 6, 7]; + const winningSecondNumbers = [1, 2, 3, 4, 5, 7, 6]; + const notWinningNumbers = [7, 8, 9, 10, 11, 12, 13]; const lotto = Lotto.create(lottoNumbers); - expect(lotto.result(winningNumbers)).toBe(NUMBER.SECOND_GRADE_INDEX); + expect(lotto.result(winningFirstNumbers)).toBe(NUMBER.FIRST_GRADE_INDEX); + expect(lotto.result(winningSecondNumbers)).toBe(NUMBER.SECOND_GRADE_INDEX); + expect(lotto.result(notWinningNumbers)).toBe(NUMBER.NOT_WINNING_INDEX); }); }); From 69cb517563736ef64799ae1bf29c7aef93901def Mon Sep 17 00:00:00 2001 From: "YongRae_Kim (Usage)" Date: Sun, 6 Mar 2022 14:11:11 +0900 Subject: [PATCH 15/23] =?UTF-8?q?feat:=20=EB=A1=9C=EB=98=90=20=EA=B5=AC?= =?UTF-8?q?=EB=A7=A4=EC=8B=9C=20=EC=A1=B0=EA=B1=B4(=EB=A1=9C=EB=98=90=20?= =?UTF-8?q?=EA=B0=80=EA=B2=A9=EC=9C=BC=EB=A1=9C=20=EB=82=98=EB=88=84?= =?UTF-8?q?=EC=96=B4=20=EB=96=A8=EC=96=B4=EC=A0=B8=EC=95=BC=20=ED=95=9C?= =?UTF-8?q?=EB=8B=A4)=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/js/__tests__/lottoGame.test.js | 14 +++++++++++++- src/js/constants/errorMessage.js | 3 ++- src/js/models/LottoRound.js | 13 +++++++++---- src/js/utils/validator.js | 8 ++++++-- 4 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/js/__tests__/lottoGame.test.js b/src/js/__tests__/lottoGame.test.js index 31fcd6cea5..a56775b4b1 100644 --- a/src/js/__tests__/lottoGame.test.js +++ b/src/js/__tests__/lottoGame.test.js @@ -19,10 +19,22 @@ describe('로또 게임 모델 테스트', () => { it('금액은 1000이상의 숫자여야한다.', () => { const lottoRound = new LottoRound(); const lessThanLottoPriceCharge = 500; + try { lottoRound.exchangeChargeToLottoAmount(lessThanLottoPriceCharge); } catch ({ message }) { - expect(message).toEqual(ERROR_MESSAGE.CHARGE_IS_INVALIDATE); + expect(message).toEqual(ERROR_MESSAGE.CHARGE_IS_NOT_ENOUGH); + } + }); + + it('금액은 1000으로 나누어 떨어지는 숫자여야한다.', () => { + const lottoRound = new LottoRound(); + const notDivisibleCharge = 1500; + + try { + lottoRound.exchangeChargeToLottoAmount(notDivisibleCharge); + } catch ({ message }) { + expect(message).toEqual(ERROR_MESSAGE.CHARGE_IS_NOT_DIVISIBLE); } }); diff --git a/src/js/constants/errorMessage.js b/src/js/constants/errorMessage.js index a1e9df1775..8e3bfd7e01 100644 --- a/src/js/constants/errorMessage.js +++ b/src/js/constants/errorMessage.js @@ -1,5 +1,6 @@ export const ERROR_MESSAGE = { - CHARGE_IS_INVALIDATE: '금액은 1000원 이상이어야합니다. 금액을 다시 입력해주세요.', + CHARGE_IS_NOT_ENOUGH: '금액은 1000원 이상이어야합니다. 금액을 다시 입력해주세요.', + CHARGE_IS_NOT_DIVISIBLE: '금액은 1000원으로 나누어 떨어져야합니다. 금액을 다시 입력해주세요.', LOTTO_NUMBER_IS_INVALIDATE: '로또 숫자들의 값이 부정확합니다. 금액을 다시 입력해주세요.', WIN_NUMBER_IS_INVALIDATE: '당첨 숫자의 범위는 1에서 45사이 입니다. 다시 입력해주세요.', DUPLICATE_NUMBER_IS_EXIST: '중복된 숫자가 포함되어 있습니다. 다시 입력해주세요.', diff --git a/src/js/models/LottoRound.js b/src/js/models/LottoRound.js index 5d1470dd4b..40ab33c7e3 100644 --- a/src/js/models/LottoRound.js +++ b/src/js/models/LottoRound.js @@ -1,7 +1,8 @@ import Lotto from './Lotto'; import { isValidNumber, - isValidCharge, + isEnoughCharge, + isDivisibleCharge, getRandomNumber, hasUniqueElement, } from '../utils/validator'; @@ -46,10 +47,14 @@ class LottoRoundModel { } exchangeChargeToLottoAmount(charge) { - if (isValidCharge(charge)) { - return Math.floor(charge / NUMBER.LOTTO_PRICE); + if (!isEnoughCharge(charge)) { + throw new Error(ERROR_MESSAGE.CHARGE_IS_NOT_ENOUGH); } - throw new Error(ERROR_MESSAGE.CHARGE_IS_INVALIDATE); + + if (!isDivisibleCharge(charge)) { + throw new Error(ERROR_MESSAGE.CHARGE_IS_NOT_DIVISIBLE); + } + return charge / NUMBER.LOTTO_PRICE; } getRoundResult(winningNumbers) { diff --git a/src/js/utils/validator.js b/src/js/utils/validator.js index ac33b41068..27171761d6 100644 --- a/src/js/utils/validator.js +++ b/src/js/utils/validator.js @@ -17,8 +17,12 @@ export function isNotValidNumber(number) { return number < 1 || number > 45; } -export function isValidCharge(charge) { - return Number.isInteger(charge) && charge >= NUMBER.LOTTO_PRICE; +export function isEnoughCharge(charge) { + return charge >= NUMBER.LOTTO_PRICE; +} + +export function isDivisibleCharge(charge) { + return charge % NUMBER.LOTTO_PRICE === 0; } export function getRandomNumber(array) { From e8ca7e767b4b3f63718bf51899c23e7aca8ae00a Mon Sep 17 00:00:00 2001 From: "YongRae_Kim (Usage)" Date: Sun, 6 Mar 2022 14:36:22 +0900 Subject: [PATCH 16/23] =?UTF-8?q?refactor:=20=EA=B9=8A=EC=9D=80=20?= =?UTF-8?q?=EB=B3=B5=EC=82=AC=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/js/__tests__/lottoGame.test.js | 10 ---------- src/js/models/LottoRound.js | 2 +- src/js/utils/customPrototypeMethod.js | 4 ---- 3 files changed, 1 insertion(+), 15 deletions(-) delete mode 100644 src/js/utils/customPrototypeMethod.js diff --git a/src/js/__tests__/lottoGame.test.js b/src/js/__tests__/lottoGame.test.js index a56775b4b1..78e9fcc7b3 100644 --- a/src/js/__tests__/lottoGame.test.js +++ b/src/js/__tests__/lottoGame.test.js @@ -1,7 +1,6 @@ /* eslint-disable max-lines-per-function */ /* eslint-disable no-undef */ -import '../utils/customPrototypeMethod'; import { ERROR_MESSAGE } from '../constants/errorMessage'; import LottoRound from '../models/LottoRound'; import Lotto from '../models/Lotto'; @@ -47,15 +46,6 @@ describe('로또 게임 모델 테스트', () => { expect(lottoRound.lottoList.length).toBe(availableLottoAmount); }); - it('lottoList의 getter는 깊게 복사된 값을 반환한다.', () => { - const lottoRound = new LottoRound(); - - lottoRound.createLottoList(charge); - - const lottoListFromGetterFunc = lottoRound.getLottoList(); - expect(lottoListFromGetterFunc).toEqual(lottoRound.lottoList); - }); - it('당첨 결과를 이용하여 당첨 통계와 수익률을 반환할 수 있어야 한다.', () => { const lottoRound = new LottoRound(); const lottoList = []; diff --git a/src/js/models/LottoRound.js b/src/js/models/LottoRound.js index 40ab33c7e3..fca58f799f 100644 --- a/src/js/models/LottoRound.js +++ b/src/js/models/LottoRound.js @@ -20,7 +20,7 @@ class LottoRoundModel { } getLottoList() { - return this.lottoList.deepCopy(); + return this.lottoList; } createLottoList(chargeInput) { diff --git a/src/js/utils/customPrototypeMethod.js b/src/js/utils/customPrototypeMethod.js deleted file mode 100644 index 9e983f42ac..0000000000 --- a/src/js/utils/customPrototypeMethod.js +++ /dev/null @@ -1,4 +0,0 @@ -/* eslint no-extend-native:0 */ -Array.prototype.deepCopy = function () { - return JSON.parse(JSON.stringify(this)); -}; From 6e19d0304d2c01bcc482a9a0bfd7c8f203a7dcc3 Mon Sep 17 00:00:00 2001 From: "YongRae_Kim (Usage)" Date: Sun, 6 Mar 2022 19:53:34 +0900 Subject: [PATCH 17/23] =?UTF-8?q?refactor:=20=EC=88=98=EC=9D=B5=EB=A5=A0?= =?UTF-8?q?=20=EB=B0=98=ED=99=98=20test=EC=97=90=EC=84=9C=20=EA=B2=B0?= =?UTF-8?q?=EA=B3=BC=20=EB=B0=B0=EC=97=B4=EC=9D=98=20=EA=B0=92=20=EC=97=AD?= =?UTF-8?q?=ED=95=A0=20=EB=AA=85=EC=8B=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/index.js | 1 - src/js/__tests__/lottoGame.test.js | 12 ++++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/index.js b/src/index.js index 5560727b68..57d0d77574 100644 --- a/src/index.js +++ b/src/index.js @@ -2,7 +2,6 @@ import './css/index.css'; import './css/converter.css'; import './css/modal.css'; import './css/nanumbarungothic.css'; -import './js/utils/customPrototypeMethod'; import RacingGameManager from './js/app'; export default new RacingGameManager().init(); diff --git a/src/js/__tests__/lottoGame.test.js b/src/js/__tests__/lottoGame.test.js index 78e9fcc7b3..f1892593e3 100644 --- a/src/js/__tests__/lottoGame.test.js +++ b/src/js/__tests__/lottoGame.test.js @@ -50,14 +50,22 @@ describe('로또 게임 모델 테스트', () => { const lottoRound = new LottoRound(); const lottoList = []; const winningNumbers = [1, 2, 3, 4, 5, 6, 10]; - const result = [1, 0, 1, 1, 0, 66718333, 0]; + const expectResult = [ + (firstGradeCount = 1), + (secondGradeCount = 0), + (thirdGradeCount = 1), + (fourthGradeCount = 1), + (fifthGradeCount = 0), + (earningRate = 66718333), + (notWinningCount = 0), + ]; lottoList.push(Lotto.create([1, 2, 3, 4, 5, 6])); lottoList.push(Lotto.create([1, 2, 3, 4, 5, 7])); lottoList.push(Lotto.create([1, 2, 3, 4, 7, 8])); lottoRound.lottoList = lottoList; - expect(lottoRound.getRoundResult(winningNumbers)).toEqual(result); + expect(lottoRound.getRoundResult(winningNumbers)).toEqual(expectResult); }); it('게임 초기화가 가능해야 한다.', () => { From a4dff6168f984e72277071a4271d2deb99c09231 Mon Sep 17 00:00:00 2001 From: "YongRae_Kim (Usage)" Date: Sun, 6 Mar 2022 20:15:47 +0900 Subject: [PATCH 18/23] =?UTF-8?q?refactor:=20data=20attribute=20=EB=B0=A9?= =?UTF-8?q?=EC=8B=9D=20class=20=ED=95=A0=EB=8B=B9=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/css/index.css | 13 +++++++------ src/js/views/index.js | 4 ++-- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/css/index.css b/src/css/index.css index becd7cbff9..626613cdae 100644 --- a/src/css/index.css +++ b/src/css/index.css @@ -6,17 +6,19 @@ input[type='number']::-webkit-inner-spin-button { input:focus { border: 1px solid #00bcd4; - outline: 2px solid #00bcd4; + outline: 1px solid #00bcd4; } -input[data-invalid-state='true'] { +.invalid { background-color: #ffb0cd; - border: 1px solid #ff6464; - outline: 2px solid #ff6464; + border: 1px solid #ff6464 !important; + outline: 1px solid #ff6464 !important; } -input[data-invalid-state='false'] { +input { background-color: #ffffff; + outline: 1px solid #aaaaaa; + border: 1px solid #dddddd; } label { @@ -58,7 +60,6 @@ body { #charge-input { flex: 1; margin-right: 20px; - border: 1px solid #b4b4b4; border-radius: 4px; } diff --git a/src/js/views/index.js b/src/js/views/index.js index 980fddc42b..ea122e40db 100644 --- a/src/js/views/index.js +++ b/src/js/views/index.js @@ -88,11 +88,11 @@ class LottoRoundView { } setInvalidInputState(target) { - target.setAttribute('data-invalid-state', true); + target.classList.add('invalid'); } setValidInputState(target) { - target.setAttribute('data-invalid-state', false); + target.classList.remove('invalid'); } openResultModal(resultArray) { From 4555bf6853e393f6085164c0663cc7492f49f625 Mon Sep 17 00:00:00 2001 From: "YongRae_Kim (Usage)" Date: Sun, 6 Mar 2022 20:40:09 +0900 Subject: [PATCH 19/23] =?UTF-8?q?fix:=20=EB=B9=84=ED=91=9C=EC=A4=80=20?= =?UTF-8?q?=ED=94=84=EB=A1=9C=ED=8D=BC=ED=8B=B0=20=EC=A0=9C=EA=B1=B0=20?= =?UTF-8?q?=ED=9B=84=20querySelector=EB=A1=9C=20=EB=8C=80=EC=B2=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/js/app.js | 44 ++++++++++++++++++------------------ src/js/constants/selector.js | 7 +++++- 2 files changed, 28 insertions(+), 23 deletions(-) diff --git a/src/js/app.js b/src/js/app.js index 5a8dd8e7a2..6648bcac9f 100644 --- a/src/js/app.js +++ b/src/js/app.js @@ -13,8 +13,6 @@ class LottoRoundManager { $winNumberForm = findElement(SELECTOR.WIN_NUMBER_INPUT_FORM); $modalCloseButton = findElement(SELECTOR.MODAL_CLOSE_BUTTON); $replayButton = findElement(SELECTOR.REPLAY_BUTTON); - $lastWinNumberInput = findElement(SELECTOR.LAST_WIN_NUMBER_INPUT); - $bonusNumberInput = findElement(SELECTOR.BONUS_NUMBER_INPUT); init() { this.$chargeForm.addEventListener('submit', this.onSubmitChargeInputForm); @@ -46,27 +44,29 @@ class LottoRoundManager { }; onInputWinNumberForm = (e) => { - if (isNotValidNumber(Number(e.target.value))) { - this.lottoRoundView.setInvalidInputState(e.target); + const targetElement = e.target; + if (isNotValidNumber(Number(targetElement.value))) { + this.lottoRoundView.setInvalidInputState(targetElement); e.target.value = ''; return; } - this.lottoRoundView.setValidInputState(e.target); - if (e.target.value.length === 2) { - if (e.target.nextElementSibling !== null) { - e.target.nextElementSibling.focus(); - return; - } - if (e.target === this.$lastWinNumberInput) { - this.$bonusNumberInput.focus(); - } + this.lottoRoundView.setValidInputState(targetElement); + if (targetElement.value.length !== 2) { + return; + } + if (targetElement.nextElementSibling !== null) { + targetElement.nextElementSibling.focus(); + return; + } + if (targetElement === findElement(SELECTOR.WIN_NUMBER_INPUT_6)) { + findElement(SELECTOR.BONUS_NUMBER_INPUT).focus(); } }; onSubmitWinNumberInputForm = (e) => { e.preventDefault(); try { - const inputWinNumber = this.getInputWinNumber(e); + const inputWinNumber = this.getInputWinNumber(); const roundResult = this.lottoRoundModel.getRoundResult(inputWinNumber); this.lottoRoundView.openResultModal(roundResult); } catch (message) { @@ -74,15 +74,15 @@ class LottoRoundManager { } }; - getInputWinNumber(e) { + getInputWinNumber() { return [ - Number(e.path[0][0].value), - Number(e.path[0][1].value), - Number(e.path[0][2].value), - Number(e.path[0][3].value), - Number(e.path[0][4].value), - Number(e.path[0][5].value), - Number(e.path[0][6].value), + Number(findElement(SELECTOR.WIN_NUMBER_INPUT_1).value), + Number(findElement(SELECTOR.WIN_NUMBER_INPUT_2).value), + Number(findElement(SELECTOR.WIN_NUMBER_INPUT_3).value), + Number(findElement(SELECTOR.WIN_NUMBER_INPUT_4).value), + Number(findElement(SELECTOR.WIN_NUMBER_INPUT_5).value), + Number(findElement(SELECTOR.WIN_NUMBER_INPUT_6).value), + Number(findElement(SELECTOR.BONUS_NUMBER_INPUT).value), ]; } diff --git a/src/js/constants/selector.js b/src/js/constants/selector.js index 25d800deaf..14051812c0 100644 --- a/src/js/constants/selector.js +++ b/src/js/constants/selector.js @@ -2,7 +2,12 @@ export const SELECTOR = { CHARGE_INPUT_FORM: '#charge-input-form', CHARGE_INPUT: '#charge-input', WIN_NUMBER_INPUT_FORM: '#win-number-input-form', - LAST_WIN_NUMBER_INPUT: '#win-number-6', + WIN_NUMBER_INPUT_1: '#win-number-1', + WIN_NUMBER_INPUT_2: '#win-number-2', + WIN_NUMBER_INPUT_3: '#win-number-3', + WIN_NUMBER_INPUT_4: '#win-number-4', + WIN_NUMBER_INPUT_5: '#win-number-5', + WIN_NUMBER_INPUT_6: '#win-number-6', BONUS_NUMBER_INPUT: '#bonus-number', ALIGN_CONVERTER: '#align-converter', From f097ca723c73823f301fdf8a9a9911d2045d0c05 Mon Sep 17 00:00:00 2001 From: "YongRae_Kim (Usage)" Date: Sun, 6 Mar 2022 21:10:54 +0900 Subject: [PATCH 20/23] =?UTF-8?q?refactor:=20early=20return=20=EC=9D=84=20?= =?UTF-8?q?=EC=9D=B4=EC=9A=A9=ED=95=9C=20depth=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/js/models/LottoRound.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/js/models/LottoRound.js b/src/js/models/LottoRound.js index fca58f799f..ee12d16e33 100644 --- a/src/js/models/LottoRound.js +++ b/src/js/models/LottoRound.js @@ -58,18 +58,18 @@ class LottoRoundModel { } getRoundResult(winningNumbers) { - if (isValidNumber(winningNumbers)) { - if (hasUniqueElement(winningNumbers)) { - this.winningResult = [0, 0, 0, 0, 0, 0, 0]; - this.lottoList.forEach((lotto) => { - this.updateLottoRankResult(lotto, winningNumbers); - }); - this.updateLottoEarningRate(); - return this.winningResult; - } + if (!isValidNumber(winningNumbers)) { + throw new Error(ERROR_MESSAGE.WIN_NUMBER_IS_INVALIDATE); + } + if (!hasUniqueElement(winningNumbers)) { throw new Error(ERROR_MESSAGE.DUPLICATE_NUMBER_IS_EXIST); } - throw new Error(ERROR_MESSAGE.WIN_NUMBER_IS_INVALIDATE); + this.winningResult = [0, 0, 0, 0, 0, 0, 0]; + this.lottoList.forEach((lotto) => { + this.updateLottoRankResult(lotto, winningNumbers); + }); + this.updateLottoEarningRate(); + return this.winningResult; } updateLottoRankResult(lotto, winningNumbers) { From e405782791049db70309006d44210a2683a88b14 Mon Sep 17 00:00:00 2001 From: "YongRae_Kim (Usage)" Date: Sun, 6 Mar 2022 21:15:44 +0900 Subject: [PATCH 21/23] =?UTF-8?q?fix:=20=EC=88=98=EC=9D=B5=EB=A5=A0=20?= =?UTF-8?q?=EC=97=B0=EC=82=B0=20=EB=A1=9C=EC=A7=81=20=EC=98=A4=EB=A5=98=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/js/__tests__/lottoGame.test.js | 21 ++++++++++++++------- src/js/models/LottoRound.js | 2 +- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/js/__tests__/lottoGame.test.js b/src/js/__tests__/lottoGame.test.js index f1892593e3..bfe1325e93 100644 --- a/src/js/__tests__/lottoGame.test.js +++ b/src/js/__tests__/lottoGame.test.js @@ -50,14 +50,21 @@ describe('로또 게임 모델 테스트', () => { const lottoRound = new LottoRound(); const lottoList = []; const winningNumbers = [1, 2, 3, 4, 5, 6, 10]; + const firstGradeCount = 1; + const secondGradeCount = 0; + const thirdGradeCount = 1; + const fourthGradeCount = 1; + const fifthGradeCount = 0; + const earningRate = 66718233; + const notWinningCount = 0; const expectResult = [ - (firstGradeCount = 1), - (secondGradeCount = 0), - (thirdGradeCount = 1), - (fourthGradeCount = 1), - (fifthGradeCount = 0), - (earningRate = 66718333), - (notWinningCount = 0), + firstGradeCount, + secondGradeCount, + thirdGradeCount, + fourthGradeCount, + fifthGradeCount, + earningRate, + notWinningCount, ]; lottoList.push(Lotto.create([1, 2, 3, 4, 5, 6])); diff --git a/src/js/models/LottoRound.js b/src/js/models/LottoRound.js index ee12d16e33..9a91ca8a3f 100644 --- a/src/js/models/LottoRound.js +++ b/src/js/models/LottoRound.js @@ -85,7 +85,7 @@ class LottoRoundModel { NUMBER.FOURTH_GRADE_PRIZE * this.winningResult[NUMBER.FOURTH_GRADE_INDEX] + NUMBER.FIFTH_GRADE_PRIZE * this.winningResult[NUMBER.FIFTH_GRADE_INDEX]; this.winningResult[NUMBER.EARNING_RATE_INDEX] = Math.floor( - (totalWinningMoney / totalCharge) * 100 + ((totalWinningMoney - totalCharge) / totalCharge) * 100 ); } } From 6e8b087346336c6e11272bddfbdfdcbd2d5e2d80 Mon Sep 17 00:00:00 2001 From: "YongRae_Kim (Usage)" Date: Mon, 7 Mar 2022 21:01:01 +0900 Subject: [PATCH 22/23] =?UTF-8?q?refactor:=20=EB=B3=B4=EB=84=88=EC=8A=A4?= =?UTF-8?q?=20=EB=B2=88=ED=98=B8=20=ED=99=95=EC=9D=B8=20=EB=A1=9C=EC=A7=81?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/js/models/Lotto.js | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/js/models/Lotto.js b/src/js/models/Lotto.js index 3a282efedf..2023f218cd 100644 --- a/src/js/models/Lotto.js +++ b/src/js/models/Lotto.js @@ -16,21 +16,17 @@ class Lotto { result(winningNumbers) { let countMatchNumber = 0; - let isContainBonusNumber = false; this.lottoNumbers.forEach((number) => { if (winningNumbers.includes(number)) { countMatchNumber += 1; - if (number === winningNumbers[NUMBER.BONUS_NUMBER]) { - isContainBonusNumber = true; - } } }); - return this.getLottoRank(countMatchNumber, isContainBonusNumber); + return this.getLottoRank(countMatchNumber, winningNumbers[NUMBER.BONUS_NUMBER]); } - getLottoRank(countMatchNumber, isContainBonusNumber) { + getLottoRank(countMatchNumber, bonusNumber) { switch (countMatchNumber) { case 3: return NUMBER.FIFTH_GRADE_INDEX; @@ -39,7 +35,9 @@ class Lotto { case 5: return NUMBER.THIRD_GRADE_INDEX; case 6: - if (isContainBonusNumber) return NUMBER.SECOND_GRADE_INDEX; + if (this.lottoNumbers.some((number) => number === bonusNumber)) { + return NUMBER.SECOND_GRADE_INDEX; + } return NUMBER.FIRST_GRADE_INDEX; default: return NUMBER.NOT_WINNING_INDEX; From 5493d95cfba9a0028bea2e61b2aaca2f9ec30b0e Mon Sep 17 00:00:00 2001 From: "YongRae_Kim (Usage)" Date: Mon, 7 Mar 2022 21:20:13 +0900 Subject: [PATCH 23/23] =?UTF-8?q?refactor:=20lottoSection=EC=9D=98=20defau?= =?UTF-8?q?lt=20state=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/js/constants/elementProperty.js | 3 +-- src/js/constants/number.js | 4 ++-- src/js/views/index.js | 21 ++++++++------------- 3 files changed, 11 insertions(+), 17 deletions(-) diff --git a/src/js/constants/elementProperty.js b/src/js/constants/elementProperty.js index c0473de65e..95bdb32234 100644 --- a/src/js/constants/elementProperty.js +++ b/src/js/constants/elementProperty.js @@ -1,5 +1,4 @@ export const ELEMENT_PROPERTY = { - HEIGHT_OF_ONE_LOTTO_ICON_LINE: 46.364, + HEIGHT_OF_ONE_LOTTO_ICON_LINE: 46, GAP_OF_LOTTO_ITEM: 3, - DEFAULT_HEIGHT_OF_LOTTO_SECTION: 237.84, }; diff --git a/src/js/constants/number.js b/src/js/constants/number.js index e98103d5e9..0561b189c4 100644 --- a/src/js/constants/number.js +++ b/src/js/constants/number.js @@ -17,7 +17,7 @@ export const NUMBER = { EARNING_RATE_INDEX: 5, NOT_WINNING_INDEX: 6, LOTTO_ELEMENT_PER_LINE: 7, - LOTTO_SECTIONS_DEFALUT_CAPACITY_IN_ICON: 35, - LOTTO_SECTIONS_DEFALUT_CAPACITY_IN_DETAIL: 5, + LOTTO_SECTIONS_DEFALUT_CAPACITY_IN_ICON: 7, + LOTTO_SECTIONS_DEFALUT_CAPACITY_IN_DETAIL: 1, ANIMATION_TIME: 500, }; diff --git a/src/js/views/index.js b/src/js/views/index.js index ea122e40db..da764bf0b2 100644 --- a/src/js/views/index.js +++ b/src/js/views/index.js @@ -45,19 +45,14 @@ class LottoRoundView { `; } - // 내부 구현이 너무 길어져서 메서드를 분리 renderAlignState(visibleState, lottoAmount = 0) { if (visibleState) { - if (lottoAmount > NUMBER.LOTTO_SECTIONS_DEFALUT_CAPACITY_IN_DETAIL) { - this.$lottoSection.style.height = this.#calculateVisibleLottoSectionHeight(lottoAmount); - this.$alignConverter.setAttribute('disabled', true); - setTimeout(() => { - this.$lottoContainer.setAttribute('data-visible-state', visibleState); - this.$alignConverter.removeAttribute('disabled'); - }, NUMBER.ANIMATION_TIME); - return; - } - this.$lottoContainer.setAttribute('data-visible-state', visibleState); + this.$lottoSection.style.height = this.#calculateVisibleLottoSectionHeight(lottoAmount); + this.$alignConverter.setAttribute('disabled', true); + setTimeout(() => { + this.$lottoContainer.setAttribute('data-visible-state', visibleState); + this.$alignConverter.removeAttribute('disabled'); + }, NUMBER.ANIMATION_TIME); return; } this.$lottoContainer.setAttribute('data-visible-state', visibleState); @@ -77,10 +72,10 @@ class LottoRoundView { return `${ linesOfLottoIcon * (ELEMENT_PROPERTY.HEIGHT_OF_ONE_LOTTO_ICON_LINE + ELEMENT_PROPERTY.GAP_OF_LOTTO_ITEM) + - ELEMENT_PROPERTY.DEFAULT_HEIGHT_OF_LOTTO_SECTION + ELEMENT_PROPERTY.HEIGHT_OF_ONE_LOTTO_ICON_LINE }px`; } - return `${ELEMENT_PROPERTY.DEFAULT_HEIGHT_OF_LOTTO_SECTION}px`; + return `${ELEMENT_PROPERTY.HEIGHT_OF_ONE_LOTTO_ICON_LINE}px`; } renderWinNumberInputSection(visibleState) {