Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
6224d54
docs: todo list 정리
usageness Feb 28, 2022
f1e648a
feat: 로또 모델에서 등수 반환 구현
usageness Feb 28, 2022
d4cadf9
feat: 당첨 결과를 이용하여 통계와 수익률을 반환할 수 있다
usageness Feb 28, 2022
19039ca
feat: 게임 초기화가 가능해야 한다.
usageness Mar 1, 2022
fc6104f
feat: 결과 모달창 마크 업 작성
usageness Mar 1, 2022
ce1ecb4
feat: 결과를 보여주는 modal view 구현
usageness Mar 2, 2022
26dc565
feat: css 유저 편의성 개선
usageness Mar 2, 2022
d34d366
feat: 당첨 번호 유효성 검사 로직 추가
usageness Mar 3, 2022
b64913d
feat: 로또 컨테이너의 높이 값이 늘어날 경우 애니메이션 적용
usageness Mar 3, 2022
cc065f2
fix: 애니메이션중 클릭시 버그 수정
usageness Mar 4, 2022
bdeff9f
feat: 당첨 번호 유효성 검사 및 다음 번호 자동 포커싱 구현
usageness Mar 4, 2022
cb33016
refactor: LottoGame.js -> LottoRound.js 파일 이름 및 메소드 이름 변경
usageness Mar 4, 2022
47df9c7
chore: 중복되는 css 할당 수정
usageness Mar 6, 2022
c88a799
test: 로또 모델 테스트 케이스 보완
usageness Mar 6, 2022
69cb517
feat: 로또 구매시 조건(로또 가격으로 나누어 떨어져야 한다) 추가
usageness Mar 6, 2022
e8ca7e7
refactor: 깊은 복사 메서드 제거
usageness Mar 6, 2022
6e19d03
refactor: 수익률 반환 test에서 결과 배열의 값 역할 명시
usageness Mar 6, 2022
a4dff61
refactor: data attribute 방식 class 할당으로 변경
usageness Mar 6, 2022
4555bf6
fix: 비표준 프로퍼티 제거 후 querySelector로 대체
usageness Mar 6, 2022
f097ca7
refactor: early return 을 이용한 depth 제거
usageness Mar 6, 2022
e405782
fix: 수익률 연산 로직 오류 수정
usageness Mar 6, 2022
6e8b087
refactor: 보너스 번호 확인 로직 변경
usageness Mar 7, 2022
5493d95
refactor: lottoSection의 default state 제거
usageness Mar 7, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@ 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,
'newline-before-return': 0,
'no-undefined': 0,
'no-constant-condition': 0,
'no-unused-private-class-members': 0,
'lines-between-class-members': 0,
},
};
2 changes: 2 additions & 0 deletions docs/todo.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,5 @@
- [✅] 로또 게임 모델에 금액이 정상적으로 입력되면, 구매할 수 있는 로또의 수를 반환할 수 있어야 한다.
- [✅] 금액은 1000이상의 숫자여야한다.
- [✅] 로또 번호 배열들을 입력하여 로또 모델을 생성하고 관리할 수 있어야 한다.
- [✅] 당첨 결과를 이용하여 당첨 통계와 수익률을 반환할 수 있어야 한다.
- [✅] 게임 초기화가 가능해야 한다.
Binary file added images/modal_close_button.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
71 changes: 60 additions & 11 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@
<h1 class="header-title">🎱 행운의 로또</h1>
<section id="charge-input-section" aria-labelledby="charge-input-section-title">
<h1 id="charge-input-section-title" hidden>금액을 입력하는 섹션입니다.</h1>
<p>구입할 금액을 입력해주세요</p>
<p>구입할 금액을 입력해주세요.</p>
<form id="charge-input-form">
<input id="charge-input" type="number" placeholder="금액" />
<button id="charge-button">구입</button>
</form>
</section>

<section id="lotto-section" aria-labelledby="lotto-section-title">
<section id="lotto-section" aria-labelledby="lotto-section-title" data-visible-state="false">
<h1 id="lotto-section-title" hidden>구매한 로또를 확인하는 섹션입니다.</h1>
<div class="lotto-wrapper">
<span id="purchased-message"></span>
Expand All @@ -35,31 +35,80 @@ <h1 id="lotto-section-title" hidden>구매한 로또를 확인하는 섹션입
</div>
</section>

<section id="win-number-input-section" aria-labelledby="win-number-input-title">
<section
id="win-number-input-section"
aria-labelledby="win-number-input-title"
data-visible-state="false"
>
<h1 id="win-number-input-title" hidden>당첨 번호 입력 섹션</h1>
<p>지난 주 당첨번호 6개와 보너스 번호 1개를 입력해주세요.</p>
<p class="win-number-input-notice">
지난 주 당첨번호 6개와 보너스 번호 1개를 입력해주세요.
</p>
<form id="win-number-input-form">
<div class="win-number-input-wrapper">
<div>
<p>당첨 번호</p>
<input id="win-number-1" type="number" />
<input id="win-number-2" type="number" />
<input id="win-number-3" type="number" />
<input id="win-number-4" type="number" />
<input id="win-number-5" type="number" />
<input id="win-number-6" type="number" />
<input id="win-number-1" type="number" min="1" max="45" />
<input id="win-number-2" type="number" min="1" max="45" />
<input id="win-number-3" type="number" min="1" max="45" />
<input id="win-number-4" type="number" min="1" max="45" />
<input id="win-number-5" type="number" min="1" max="45" />
<input id="win-number-6" type="number" min="1" max="45" />
</div>

<div class="bonus-number-wrapper">
<p>보너스 번호</p>
<input id="bonus-number" type="number" />
<input id="bonus-number" type="number" min="1" max="45" />
</div>
</div>

<button id="result-button">결과 확인하기</button>
</form>
</section>
</div>

<div id="result-modal-area" data-visible-state="false">
<div class="background-area">
<div class="modal">
<button id="modal-close-button"></button>
<h2 class="modal-title">🏆 당첨 통계 🏆</h2>
<ul class="winning-statistics-table">
<li class="table-head">
<p>일치 갯수</p>
<p>당첨금</p>
<p>당첨 갯수</p>
</li>
<li>
<p>3개</p>
<p>5,000</p>
<p id="fifth-grade-amount">n개</p>
</li>
<li>
<p>4개</p>
<p>50,000</p>
<p id="fourth-grade-amount">n개</p>
</li>
<li>
<p>5개</p>
<p>1,500,000</p>
<p id="third-grade-amount">n개</p>
</li>
<li>
<p>5개+보너스볼</p>
<p>30,000,000</p>
<p id="second-grade-amount">n개</p>
</li>
<li>
<p>6개</p>
<p>2,000,000,000</p>
<p id="first-grade-amount">n개</p>
</li>
</ul>
<p id="earning-rate-notice">당신의 총 수익률은 %입니다.</p>
<button id="replay-button">다시 시작하기</button>
</div>
</div>
</div>
<script type="module" src="./src/index.js"></script>
</body>
</html>
78 changes: 69 additions & 9 deletions src/css/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,44 @@ input[type='number']::-webkit-inner-spin-button {
margin: 0;
}

input:focus {
border: 1px solid #00bcd4;
outline: 1px solid #00bcd4;
}

.invalid {
background-color: #ffb0cd;
border: 1px solid #ff6464 !important;
outline: 1px solid #ff6464 !important;
}

input {
outline: none;
background-color: #ffffff;
outline: 1px solid #aaaaaa;
border: 1px solid #dddddd;
}

label {
cursor: pointer;
}

body {
width: 98vw;
height: 90vh;
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 {
width: 25vw;
min-width: 414px;
padding: 50px;
padding: 20px;

background-color: #ffffff;
border: 1px solid rgba(0, 0, 0, 0.12);
Expand All @@ -42,25 +60,42 @@ body {
#charge-input {
flex: 1;
margin-right: 20px;
border: 1px solid #b4b4b4;
border-radius: 4px;
}

#charge-button {
width: 15%;
}

button {
border-radius: 4px;
background-color: #00bcd4;
color: #ffffff;
border: 0;
min-height: 36px;
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;
visibility: visible;
transition: height 0.5s;
}

.lotto-wrapper {
Expand All @@ -77,10 +112,12 @@ section {

#lotto-container {
display: flex;
flex-wrap: wrap;
}

#lotto-container[data-visible-state='false'] {
flex-direction: row;
gap: 10px;
gap: 3px;
}

#lotto-container[data-visible-state='false'] .number {
Expand All @@ -97,26 +134,49 @@ section {
gap: 10px;
}

#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 {
margin-bottom: 0;
}

.win-number-input-wrapper {
display: flex;
gap: 10px;
justify-content: space-between;
}

.win-number-input-wrapper > div > input {
text-align: center;
}

#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 {
Expand Down
70 changes: 70 additions & 0 deletions src/css/modal.css
Original file line number Diff line number Diff line change
@@ -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: fixed;
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;
}
2 changes: 1 addition & 1 deletion src/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
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();
16 changes: 16 additions & 0 deletions src/js/__tests__/lotto.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
/* eslint-disable max-lines-per-function */
/* eslint-disable no-undef */

import { ERROR_MESSAGE } from '../constants/errorMessage';
import { NUMBER } from '../constants/number';
import Lotto from '../models/Lotto';

describe('로또 모델 테스트', () => {
Expand All @@ -15,4 +19,16 @@ describe('로또 모델 테스트', () => {
expect(message).toEqual(ERROR_MESSAGE.LOTTO_NUMBER_IS_INVALIDATE);
}
});

it('로또 모델의 번호와 당첨 번호를 비교하여 등수를 반환할 수 있어야 한다.', () => {
const lottoNumbers = [1, 2, 3, 4, 5, 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(winningFirstNumbers)).toBe(NUMBER.FIRST_GRADE_INDEX);
expect(lotto.result(winningSecondNumbers)).toBe(NUMBER.SECOND_GRADE_INDEX);
expect(lotto.result(notWinningNumbers)).toBe(NUMBER.NOT_WINNING_INDEX);
});
});
Loading