-
Notifications
You must be signed in to change notification settings - Fork 168
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[2단계 - 웹 기반 로또 게임] 해리(최현웅) 미션 제출합니다. #314
Merged
Merged
Changes from all commits
Commits
Show all changes
26 commits
Select commit
Hold shift + click to select a range
c8a7683
docs(REQUEST-STEP2.md): 기능 요구 사항 작성
hwinkr df38d02
docs(REQUEST-STEP2.md): 기능 요구 사항 작성
hwinkr a24d1ed
chore: .gitignore에 dist 폴더 삭제
hwinkr 292553f
feat(index.html): 웹 기반 로또 게임 html 레이아웃 작성
hwinkr 577e6d0
config(packaga.json): build 명령어 추가
hwinkr b59c89f
feat(step2-index.js): 웹 기반 로또 게임 엔트리 구현
hwinkr fc0233c
chore(index.html): id 이름 변경
hwinkr 2916c87
chore(constants): 웹 기반 로또 게임에서 사용할 상수 객체 설정
hwinkr c6d5447
chore(index.html): id 이름 변경
hwinkr 13a644f
chore(constants): 웹 기반 로또 게임에서 사용할 상수 객체 설정
hwinkr db43665
feat(LottoController): dom, domain을 연결하는 로또 게임 컨트롤러 구현
hwinkr 0e1de6e
feat(event.js): 웹 기반 로또 게임에서 발생하는 이벤트 핸들러 등록 함수 구현
hwinkr 651aa12
feat(LottoPurchaseForm): 로또 구입 폼 뷰 구현
hwinkr db25f4b
feat(WinningLottoForm): 당첨 로또 입력 폼 뷰 구현
hwinkr 4296d99
feat(WinningResult): 당첨 결과 모달 뷰 구현
hwinkr 228b01a
chore(add step1 domains): step1에서 구현한 로또 게임 도메인 로직 추가
hwinkr c6c5dec
feat(common styles): 공통으로 사용하는 css 분리
hwinkr 52b2df0
feat(layout styles): 레이아웃 설정 css 구현
hwinkr 25b3284
feat(reset styles): reset css
hwinkr 0186fac
docs(REQUEST-STEP2.md): 기능 요구사항 완료
hwinkr 7da2588
chore(add id): FormData를 활용하기 위한 id 추가
hwinkr ef38abb
refactor(LottoController): 구입한 로또 수량 인자 제거
hwinkr 1d1e309
refactor(event): FormData 객체를 사용하는 것으로 변경
hwinkr 78ef8af
refactor(LottoPurchaseForm): 스크롤 메시지 판단 로직 변경
hwinkr 5aa3bf2
chore(common): game-container 스타일에 min-width 추가
hwinkr 70d5477
chore(common): game-container 스타일에 min-width 추가
hwinkr File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
node_modules/ | ||
dist/ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
# 🎱 웹 기반 로또 애플리케이션 | ||
|
||
## 도메인 | ||
|
||
### 로또 | ||
|
||
- 로또는 1 ~ 45의 6개의 숫자로 구성되어있다. | ||
|
||
다음의 유효성 검증을 진행한다. | ||
|
||
- [x] 숫자가 아닌 문자열이 들어오면 안된다. | ||
- [x] 6개의 숫자로 구성되어야 한다. | ||
- [x] 1 ~ 45 사이의 숫자여야 한다. | ||
- [x] 로또는 중복된 숫자를 가질 수 없다 | ||
|
||
- [x] 로또 도메인은 당첨 로또와 비교했을 때, 몇개 일치하는지 판단하고 결과를 외부에 전달한다. | ||
|
||
### 당첨 로또 | ||
|
||
- 당첨 로또는 6개의 로또 번호와 보너스 번호를 가진다. | ||
|
||
다음의 유효성 검증을 진행한다. | ||
|
||
- [x] 숫자가 아닌 문자열이 들어오면 안된다. | ||
- [x] 6개의 숫자로 구성되어야 한다. | ||
- [x] 1 ~ 45 사이의 숫자여야 한다. | ||
- [x] 로또는 중복된 숫자를 가질 수 없다 | ||
- [x] 당첨 로또 6개와 보너스 번호는 중복될 수 없다. | ||
|
||
### 로또 상점 | ||
|
||
- [x] 로또 구입 금액을 입력하면 구입 금액에 해당하는 만큼 로또를 발행해야 한다. | ||
- 로또 1장의 가격은 1,000원이다. | ||
|
||
다음의 유효성 검증을 진행한다. | ||
|
||
- [x] 로또 가격은 문자열(공백)이 될 수 없다. | ||
- [x] 로또 가격은 1,000으로 나누어떨어져야 한다. | ||
|
||
### 로또 결과 | ||
|
||
- [x] 로또 결과판을 만든다. | ||
- 등수와 각 등수의 갯수 정보로 구성되어있다. | ||
- [x] 수익률을 계산한다. | ||
- 수익률은 `총 당첨금/구입 금액`이다. | ||
- 수익률은 반올림하여 소수점 2자리 수까지 계산한다. | ||
- 당첨은 1등부터 5등까지 있다. 당첨 기준과 금액은 아래와 같다. | ||
|
||
```text | ||
1등: 6개 번호 일치 / 2,000,000,000원 | ||
2등: 5개 번호 + 보너스 번호 일치 / 30,000,000원 | ||
3등: 5개 번호 일치 / 1,500,000원 | ||
4등: 4개 번호 일치 / 50,000원 | ||
5등: 3개 번호 일치 / 5,000원 | ||
``` | ||
|
||
## 입력 | ||
|
||
- [x] input 태그를 활용하여 로또 구입 금액을 입력받는다. | ||
- [x] 유효하지 않은 입력의 경우 에러 메시지를 input 태그 아래에 표시한다 | ||
|
||
![alt text](image.png) | ||
|
||
- [x] input 태그를 활용하여 지난 주 당첨 번호 6개와 보너스 번호를 입력 받는다. | ||
- [x] 유효하지 않은 입력의 경우 에러 메시지를 input 태그 아래에 표시한다 | ||
|
||
![alt text](image-1.png) | ||
|
||
## 출력 | ||
|
||
- [x] 상단바에 **🎱 행운의 로또** UI를 구성한다. | ||
- [x] 하단바에 **Copyright 2024 woowacourse** UI를 구성한다. | ||
- [x] **🎱 내 당첨 번호 확인 🎱** UI를 구성한다. | ||
- [x] 발행한 로또 번호 UI를 구성한다. | ||
- [x] 팝업 UI를 활용하여 로또 당첨 결과와 수익률을 보여준다. |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,21 @@ | ||
/** | ||
* step 2의 시작점이 되는 파일입니다. | ||
* 노드 환경에서 사용하는 readline 등을 불러올 경우 정상적으로 빌드할 수 없습니다. | ||
*/ | ||
import "./step2/styles/reset.css"; | ||
import "./step2/styles/layout.css"; | ||
import "./step2/styles/common.css"; | ||
import LottoController from "./step2/controllers/LottoController"; | ||
import { | ||
registerCloseModalEvent, | ||
registerPurchaseEvent, | ||
registerRenderResultEvent, | ||
registerRestartEvent, | ||
} from "./step2/dom/event"; | ||
|
||
const lottoController = new LottoController(); | ||
|
||
registerPurchaseEvent(lottoController.purchaseLottos.bind(lottoController)); | ||
registerRenderResultEvent( | ||
lottoController.renderWinningResult.bind(lottoController), | ||
); | ||
registerCloseModalEvent( | ||
lottoController.closeWinningResultModal.bind(lottoController), | ||
); | ||
registerRestartEvent(lottoController.restartLottoGame.bind(lottoController)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
export const ERROR_MESSAGES = { | ||
invalidNumbersType: "로또 번호는 1~45 사이의 숫자여야 합니다.", | ||
invalidLottoLength: "로또 번호는 6개여야 합니다.", | ||
invalidLottoUniqueness: "로또 번호는 중복될 수 없습니다.", | ||
invalidPurchaseAmount: "구입 금액은 1000단위의 숫자여야 합니다.", | ||
invalidBonusNumberType: "보너스 번호는 1~45 사이의 숫자여야 합니다.", | ||
invalidBonusNumberUniqueness: "보너스 번호는 로또 번호와 중복될 수 없습니다.", | ||
invalidRetrySign: "재시작 신호는 y또는 n이어야 합니다.", | ||
}; | ||
|
||
export const LOTTO_RULES = { | ||
price: 1000, | ||
length: 6, | ||
minRandomNumber: 1, | ||
maxRandomNumber: 45, | ||
scrollThreadhold: 5, | ||
}; | ||
|
||
export const ELEMENT_SELECTOR = { | ||
purchaseForm: "lotto-purchase-form", | ||
purchaseInput: "lotto-purchase-input", | ||
purchasedLottoContainer: "purchased-lottos-container", | ||
winningLottoForm: "winning-lotto-form", | ||
winningLottoContainer: "winning-lotto-input-container", | ||
winningLottoInput: ".winning-lotto-input", | ||
bonusNumberContainer: "bonus-number-input-container", | ||
bonusNumberInput: "bonus-number-input", | ||
modalBackground: "winning-result-modal-background", | ||
modalCancelButton: "modal-cancel-button", | ||
restartButton: "restart-button", | ||
winningResultContent: "winning-result-content", | ||
returnRateContainer: "return-rate-container", | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import LottoStore from "../domains/LottoStore"; | ||
import WinningLotto from "../domains/WinningLotto"; | ||
import LottoResult from "../domains/LottoResult"; | ||
import Lotto from "../domains/Lotto"; | ||
import LottoPurchaseForm from "../dom/views/LottoPurcaseForm"; | ||
import WinningLottoForm from "../dom/views/WinningLottoForm"; | ||
import WinningResult from "../dom/views/WinningResult"; | ||
import { LOTTO_RULES } from "../constants/lotto"; | ||
|
||
export default class LottoController { | ||
#lottos; | ||
|
||
constructor() { | ||
this.#lottos = null; | ||
} | ||
|
||
#isInstanceOfWinningLotto(winningLotto) { | ||
return winningLotto instanceof WinningLotto; | ||
} | ||
|
||
#renderPurchasedLotto() { | ||
LottoPurchaseForm.resetPurchaseForm(); | ||
const lottoNumbers = this.#lottos.map((lotto) => lotto.getNumbers()); | ||
LottoPurchaseForm.renderPurchasedLottos(lottoNumbers); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
} | ||
|
||
#configWinningLotto(winningNumbers, bonusNumber) { | ||
try { | ||
const winninbNumberArray = winningNumbers.map((winningNumber) => | ||
Number(winningNumber) | ||
); | ||
return new WinningLotto( | ||
new Lotto(winninbNumberArray), | ||
Number(bonusNumber) | ||
); | ||
} catch (error) { | ||
alert(error.message); | ||
WinningLottoForm.resetWinningLottoForm(); | ||
WinningLottoForm.focusFirstWinningLottoInput(); | ||
} | ||
} | ||
|
||
purchaseLottos(purchaseAmount) { | ||
try { | ||
this.#lottos = LottoStore.purchaseLottos(purchaseAmount); | ||
this.#renderPurchasedLotto(); | ||
WinningLottoForm.renderWinningLottoForm(); | ||
} catch (error) { | ||
alert(error.message); | ||
LottoPurchaseForm.resetPurchaseForm(); | ||
LottoPurchaseForm.focusPurchaseInput(); | ||
} | ||
} | ||
|
||
renderWinningResult(winningNumbers, bonusNumber) { | ||
const winningLotto = this.#configWinningLotto(winningNumbers, bonusNumber); | ||
if (!this.#isInstanceOfWinningLotto(winningLotto)) return; | ||
|
||
const lottoResult = new LottoResult(); | ||
lottoResult.generateResult(this.#lottos, winningLotto); | ||
const lottoRankBoard = lottoResult.getRankBoard(); | ||
const returnRate = lottoResult.calculateReturnRate( | ||
this.#lottos.length * LOTTO_RULES.price | ||
); | ||
|
||
WinningResult.renderWinningResult(lottoRankBoard, returnRate); | ||
} | ||
|
||
closeWinningResultModal() { | ||
WinningResult.closeResultModal(); | ||
} | ||
|
||
restartLottoGame() { | ||
this.closeWinningResultModal(); | ||
LottoPurchaseForm.resetPurchaseForm(); | ||
LottoPurchaseForm.focusPurchaseInput(); | ||
LottoPurchaseForm.removePurchasedLottos(); | ||
WinningLottoForm.resetWinningLottoForm(); | ||
WinningLottoForm.hideWinningLottoForm(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
import { ELEMENT_SELECTOR } from "../constants/lotto"; | ||
|
||
export const registerPurchaseEvent = (purchaseCallback) => { | ||
const lottoPurchaseForm = document.getElementById( | ||
ELEMENT_SELECTOR.purchaseForm | ||
); | ||
|
||
lottoPurchaseForm.addEventListener("submit", (event) => { | ||
event.preventDefault(); | ||
|
||
const formData = new FormData(lottoPurchaseForm); | ||
const lottoPurchaseAmount = formData.get("lotto-purchase-input"); | ||
purchaseCallback(lottoPurchaseAmount); | ||
}); | ||
}; | ||
|
||
const getWinningLottoNumbers = () => { | ||
const winningLottoInputs = document.querySelectorAll( | ||
ELEMENT_SELECTOR.winningLottoInput | ||
); | ||
|
||
return [...winningLottoInputs].map((winningNumber) => { | ||
return winningNumber.value; | ||
}); | ||
}; | ||
|
||
const getBonusNumber = () => { | ||
const bonusNumber = document.getElementById( | ||
ELEMENT_SELECTOR.bonusNumberInput | ||
); | ||
|
||
return bonusNumber.value; | ||
}; | ||
|
||
export const registerRenderResultEvent = (renderResultCallback) => { | ||
const winningLottoForm = document.getElementById( | ||
ELEMENT_SELECTOR.winningLottoForm | ||
); | ||
|
||
winningLottoForm.addEventListener("submit", (event) => { | ||
event.preventDefault(); | ||
const winningNumbers = getWinningLottoNumbers(); | ||
const bonusNumber = getBonusNumber(); | ||
renderResultCallback(winningNumbers, bonusNumber); | ||
}); | ||
}; | ||
|
||
export const registerCloseModalEvent = (closeCallback) => { | ||
const modalBackground = document.getElementById( | ||
ELEMENT_SELECTOR.modalBackground | ||
); | ||
const modalCancelButton = document.getElementById( | ||
ELEMENT_SELECTOR.modalCancelButton | ||
); | ||
|
||
modalCancelButton.addEventListener("click", () => { | ||
closeCallback(); | ||
}); | ||
|
||
modalBackground.addEventListener("click", (event) => { | ||
if (event.target === event.currentTarget) { | ||
closeCallback(); | ||
} | ||
}); | ||
}; | ||
|
||
export const registerRestartEvent = (restartCallback) => { | ||
const restartButton = document.getElementById(ELEMENT_SELECTOR.restartButton); | ||
|
||
restartButton.addEventListener("click", () => { | ||
restartCallback(); | ||
}); | ||
}; |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
에러 메시지를 input 태그 아래에 표시하는 것은 기능 요구 사항을 적을 때는 고려했으나 구현은 하지 못했습니다. 체크 표시를 해버리고 제출했네요, 리뷰 요청을 하고나면 수정을 하면 안돼서 참고 부탁드립니다..! 😅