-
Notifications
You must be signed in to change notification settings - Fork 6
[차세진] 로또 미션 Step1 #3
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
base: chasj0326
Are you sure you want to change the base?
Changes from all commits
a2b83da
3dc2712
a3ee751
b466e19
e95ccea
f693fe0
2198c35
6c1a681
9d7e79e
712c577
60bc985
d685e27
1235582
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,4 @@ | ||
| # 자동차 경주 미션 | ||
| # 로또 미션 | ||
|
|
||
| ## 참고링크 및 저장소 | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,94 @@ | ||
| import Lotto from '../domain/Lotto.js'; | ||
| import { lottoValidations } from '../validations/lotto.js'; | ||
| import LOTTO_TYPE from '../constants/lottoType.js'; | ||
|
|
||
| describe('로또 테스트', () => { | ||
| test('로또 번호는 [당첨, 티켓] 두가지 유형을 가질 수 있다.', () => { | ||
| expect( | ||
| () => | ||
| new Lotto({ | ||
| type: 'otherType', | ||
| numbers: [1, 2, 3, 4, 5, 6], | ||
| }), | ||
| ).toThrow(lottoValidations.lottoType.errorMessage); | ||
| }); | ||
|
|
||
| test('로또 번호는 6개여야 한다.', () => { | ||
| expect( | ||
| () => | ||
| new Lotto({ | ||
| type: LOTTO_TYPE.TICKET, | ||
| numbers: [1, 2, 3, 4, 5], | ||
| }), | ||
| ).toThrow(lottoValidations.lottoNumbersLength.errorMessage); | ||
| }); | ||
|
|
||
| test('당첨 로또 번호는 보너스 번호를 가져야 한다.', () => { | ||
| expect( | ||
| () => | ||
| new Lotto({ | ||
| type: LOTTO_TYPE.WINNING, | ||
| numbers: [1, 2, 3, 4, 5, 6], | ||
| }), | ||
| ).toThrow(lottoValidations.winningLottoHasBonus.errorMessage); | ||
| }); | ||
|
|
||
| test('티켓 로또 번호는 보너스 번호가 없어야 한다.', () => { | ||
| expect( | ||
| () => | ||
| new Lotto({ | ||
| type: LOTTO_TYPE.TICKET, | ||
| numbers: [1, 2, 3, 4, 5, 6], | ||
| bonusNumber: 7, | ||
| }), | ||
| ).toThrow(lottoValidations.ticketLottoBonusNull.errorMessage); | ||
| }); | ||
|
|
||
| test('로또 번호는 각각 달라야 한다.', () => { | ||
| expect( | ||
| () => | ||
| new Lotto({ | ||
| type: LOTTO_TYPE.WINNING, | ||
| numbers: [1, 2, 3, 4, 5, 6], | ||
| bonusNumber: 6, | ||
| }), | ||
| ).toThrow(lottoValidations.lottoEachUnique.errorMessage); | ||
|
|
||
| expect( | ||
| () => | ||
| new Lotto({ | ||
| type: LOTTO_TYPE.TICKET, | ||
| numbers: [1, 2, 3, 3, 5, 6], | ||
| }), | ||
| ).toThrow(lottoValidations.lottoEachUnique.errorMessage); | ||
| }); | ||
|
|
||
| test('모든 로또 번호는 정수여야 한다.', () => { | ||
| expect( | ||
| () => | ||
| new Lotto({ | ||
| type: LOTTO_TYPE.TICKET, | ||
| numbers: [1, 2, 3, 4, 5, '6'], | ||
| }), | ||
| ).toThrow(lottoValidations.lottoInteger.errorMessage); | ||
| }); | ||
|
|
||
| test('모든 로또 번호는 1 이상 45 이하여야 한다.', () => { | ||
| expect( | ||
| () => | ||
| new Lotto({ | ||
| type: LOTTO_TYPE.WINNING, | ||
| numbers: [1, 2, 3, 4, 5, 45], | ||
| bonusNumber: 46, | ||
| }), | ||
| ).toThrow(lottoValidations.lottoRange.errorMessage); | ||
|
|
||
| expect( | ||
| () => | ||
| new Lotto({ | ||
| type: LOTTO_TYPE.TICKET, | ||
| numbers: [0, 1, 2, 3, 4, 5], | ||
| }), | ||
| ).toThrow(lottoValidations.lottoRange.errorMessage); | ||
| }); | ||
| }); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| import { createLottoTicket, createWinningLotto } from '../domain/Lotto.js'; | ||
| import LottoMatcher from '../domain/LottoMatcher.js'; | ||
| import { lottoMatcherValidations } from '../validations/lottoMatcher.js'; | ||
| import LOTTO_TYPE from '../constants/lottoType.js'; | ||
|
|
||
| describe('로또 번호 일치여부 계산 테스트', () => { | ||
| test('유효한 당첨 로또로만 계산할 수 있다.', () => { | ||
| const validLottoTicket = createLottoTicket([11, 12, 13, 14, 15, 16]); | ||
|
|
||
| expect(() => | ||
| LottoMatcher.matchLotto({ | ||
| winningLotto: { type: LOTTO_TYPE.WINNING, numbers: [1, 2, 3, 4, 5, 6], bonusNumber: 8 }, | ||
| lottoTickets: [validLottoTicket], | ||
| }), | ||
| ).toThrow(lottoMatcherValidations.validWinningLotto.errorMessage); | ||
|
|
||
| expect(() => | ||
| LottoMatcher.matchLotto({ | ||
| winningLotto: validLottoTicket, | ||
| lottoTickets: [validLottoTicket], | ||
| }), | ||
| ).toThrow(lottoMatcherValidations.validWinningLotto.errorMessage); | ||
| }); | ||
|
|
||
| test('유효한 로또 티켓들만 계산할 수 있다.', () => { | ||
| const validWinningLotto = createWinningLotto([1, 2, 3, 4, 5, 6], 7); | ||
|
|
||
| expect(() => | ||
| LottoMatcher.matchLotto({ | ||
| winningLotto: validWinningLotto, | ||
| lottoTickets: [{ type: LOTTO_TYPE.TICKET, numbers: [1, 2, 3, 4, 5, 6] }], | ||
| }), | ||
| ); | ||
|
|
||
| expect(() => | ||
| LottoMatcher.matchLotto({ | ||
| winningLotto: validWinningLotto, | ||
| lottoTickets: [validWinningLotto], | ||
| }), | ||
| ).toThrow(lottoMatcherValidations.validLottoTickets.errorMessage); | ||
| }); | ||
|
|
||
| test('로또 티켓들의 [당첨 번호 일치 개수, 보너스 번호 일치 여부]를 반환한다.', () => { | ||
| const winningLotto = createWinningLotto([1, 2, 3, 4, 5, 6], 7); | ||
| const lottoTicket1 = createLottoTicket([1, 2, 3, 14, 15, 16]); // 3, false | ||
| const lottoTicket2 = createLottoTicket([11, 12, 13, 14, 15, 16]); // 0, false | ||
| const lottoTicket3 = createLottoTicket([1, 2, 3, 4, 7, 8]); // 4, true | ||
|
|
||
| expect( | ||
| LottoMatcher.matchLotto({ | ||
| winningLotto, | ||
| lottoTickets: [lottoTicket1, lottoTicket2, lottoTicket3], | ||
| }), | ||
| ).toEqual([ | ||
| { | ||
| lotto: lottoTicket1, | ||
| matchCount: 3, | ||
| bonusMatch: false, | ||
| }, | ||
| { | ||
| lotto: lottoTicket2, | ||
| matchCount: 0, | ||
| bonusMatch: false, | ||
| }, | ||
| { | ||
| lotto: lottoTicket3, | ||
| matchCount: 4, | ||
| bonusMatch: true, | ||
| }, | ||
| ]); | ||
| }); | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| import LottoPayment from '../domain/LottoPayment.js'; | ||
| import { lottoPaymentValidations } from '../validations/lottoPayment.js'; | ||
|
|
||
| describe('로또 결제 테스트', () => { | ||
| test('로또 결제 금액은 정수여야 한다.', () => { | ||
| expect(() => | ||
| LottoPayment.createLottoTickets({ | ||
| payAmount: '1000', | ||
| }), | ||
| ).toThrow(lottoPaymentValidations.payAmountInteger.errorMessage); | ||
| }); | ||
|
|
||
| test('로또 결제는 1000원 단위로만 가능하다.', () => { | ||
| expect(() => | ||
| LottoPayment.createLottoTickets({ | ||
| payAmount: 1100, | ||
| }), | ||
| ).toThrow(lottoPaymentValidations.payAmountUnit1000.errorMessage); | ||
| }); | ||
|
|
||
| test('1000원 당 1장의 로또 티켓을 발행해야 한다.', () => { | ||
| const { lottoTickets } = LottoPayment.createLottoTickets({ | ||
| payAmount: 8000, | ||
| }) | ||
| expect(lottoTickets.length).toBe(8); | ||
| }); | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,145 @@ | ||
| import LottoSystem from '../domain/LottoSystem.js'; | ||
| import { lottoSystemValidations } from '../validations/lottoSystem.js'; | ||
| import createLottoNumbers from '../domain/createLottoNumbers.js'; | ||
|
|
||
| vi.mock('../domain/createLottoNumbers'); | ||
|
|
||
| describe('로또 시스템 테스트', async () => { | ||
| const originalCreateLottoNumbers = await vi | ||
| .importActual('../domain/createLottoNumbers') | ||
| .then((module) => module.default); | ||
|
|
||
| beforeEach(() => { | ||
| createLottoNumbers.mockReset(); | ||
| createLottoNumbers.mockImplementation(originalCreateLottoNumbers); | ||
| }); | ||
|
|
||
| test('로또 시스템은 순위가 올바르게 매겨진 랭킹 규칙만 사용한다.', () => { | ||
| const rankingRuleHasInvalidRank1 = [ | ||
| { | ||
| matchCount: 3, | ||
| bonusMatch: false, | ||
| profit: 1000, | ||
| rank: -1, | ||
| }, | ||
| ]; | ||
| expect( | ||
| () => | ||
| new LottoSystem({ | ||
| rankingRule: rankingRuleHasInvalidRank1, | ||
| }), | ||
| ).toThrow(lottoSystemValidations.validRanks.errorMessage); | ||
|
|
||
| const rankingRuleHasInvalidRank2 = [ | ||
| { | ||
| matchCount: 3, | ||
| bonusMatch: false, | ||
| profit: 1000, | ||
| rank: 3, | ||
| }, | ||
| ]; | ||
| expect( | ||
| () => | ||
| new LottoSystem({ | ||
| rankingRule: rankingRuleHasInvalidRank2, | ||
| }), | ||
| ).toThrow(lottoSystemValidations.hasAllRanks.errorMessage); | ||
| }); | ||
|
|
||
| test('로또 시스템은 유효한 matchCount, bonus, profit 이 포함된 랭킹 규칙만 사용한다.', () => { | ||
| const rankingRuleHasInvalidMatchCount = [ | ||
| { | ||
| bonusMatch: true, | ||
| profit: 1000, | ||
| rank: 1, | ||
| matchCount: 100, | ||
| }, | ||
| ]; | ||
| expect( | ||
| () => | ||
| new LottoSystem({ | ||
| rankingRule: rankingRuleHasInvalidMatchCount, | ||
| }), | ||
| ).toThrow(lottoSystemValidations.validMatchCounts.errorMessage); | ||
|
|
||
| const rankingRuleHasInvalidBonusMatch = [ | ||
| { | ||
| profit: 1000, | ||
| rank: 1, | ||
| matchCount: 3, | ||
| bonusMatch: 'false', | ||
| }, | ||
| ]; | ||
| expect( | ||
| () => | ||
| new LottoSystem({ | ||
| rankingRule: rankingRuleHasInvalidBonusMatch, | ||
| }), | ||
| ).toThrow(lottoSystemValidations.validBonusMatches.errorMessage); | ||
|
|
||
| const rankingRuleHasInvalidProfit = [ | ||
| { | ||
| bonusMatch: true, | ||
| profit: '1000', | ||
| rank: 1, | ||
| matchCount: 3, | ||
| }, | ||
| ]; | ||
| expect( | ||
| () => | ||
| new LottoSystem({ | ||
| rankingRule: rankingRuleHasInvalidProfit, | ||
| }), | ||
| ).toThrow(lottoSystemValidations.validProfits.errorMessage); | ||
| }); | ||
|
|
||
| test('로또 시스템은 정확한 개수의 로또를 구매한다.', () => { | ||
| const lottoSystem = new LottoSystem(); | ||
| lottoSystem.payLottoTicket(10000); | ||
|
|
||
| expect(lottoSystem.ticketCount).toBe(10); | ||
| expect(lottoSystem.paidAmount).toBe(10000); | ||
| }); | ||
|
|
||
| test('로또 시스템은 발행한 로또들을 등수 별로 분류할 수 있다.', () => { | ||
| createLottoNumbers | ||
| .mockReturnValueOnce([1, 2, 3, 4, 5, 6]) // 1등 | ||
| .mockReturnValueOnce([1, 2, 3, 4, 5, 7]) // 2등 | ||
| .mockReturnValueOnce([1, 2, 3, 4, 5, 7]) // 2등 | ||
| .mockReturnValueOnce([1, 2, 3, 4, 15, 16]) // 4등 | ||
| .mockReturnValueOnce([1, 2, 3, 4, 15, 16]) // 4등 | ||
| .mockReturnValueOnce([1, 2, 3, 4, 15, 16]); // 4등 | ||
|
|
||
| const lottoSystem = new LottoSystem(); | ||
| lottoSystem.setWinningLotto([1, 2, 3, 4, 5, 6], 7); | ||
| lottoSystem.payLottoTicket(6000); | ||
|
|
||
| expect(lottoSystem.lottoRankingResult.find(({ rank }) => rank === 1).ticketList.length).toBe(1); | ||
| expect(lottoSystem.lottoRankingResult.find(({ rank }) => rank === 2).ticketList.length).toBe(2); | ||
| expect(lottoSystem.lottoRankingResult.find(({ rank }) => rank === 4).ticketList.length).toBe(3); | ||
| }); | ||
|
|
||
| test('로또 시스템은 총 수익을 계산할 수 있다.', () => { | ||
| createLottoNumbers | ||
| .mockReturnValueOnce([1, 2, 3, 4, 5, 6]) // 1등 | ||
| .mockReturnValueOnce([1, 2, 3, 4, 15, 16]); // 4등 | ||
|
|
||
| const lottoSystem = new LottoSystem(); | ||
| lottoSystem.setWinningLotto([1, 2, 3, 4, 5, 6], 7); | ||
| lottoSystem.payLottoTicket(2000); | ||
|
|
||
| expect(lottoSystem.profitAmount).toBe(2000050000); | ||
|
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.
|
||
| }); | ||
|
|
||
| test('로또 시스템은 수익율을 계산할 수 있다.', () => { | ||
| createLottoNumbers | ||
| .mockReturnValueOnce([1, 2, 3, 4, 15, 16]) // 4등 = 50000 | ||
| .mockImplementation(() => [11, 12, 13, 14, 15, 16]); | ||
|
|
||
| const lottoSystem = new LottoSystem(); | ||
| lottoSystem.setWinningLotto([1, 2, 3, 4, 5, 6], 7); | ||
| lottoSystem.payLottoTicket(100000); | ||
|
|
||
| expect(lottoSystem.profitRatio).toBe(50); | ||
| }); | ||
| }); | ||
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| const LOTTO_RANKING_DATA = [ | ||
| { | ||
| rank: 1, | ||
| matchCount: 6, | ||
| profit: 2000000000, | ||
| }, | ||
| { | ||
| rank: 2, | ||
| matchCount: 5, | ||
| bonusMatch: true, | ||
| profit: 30000000, | ||
| }, | ||
| { | ||
| rank: 3, | ||
| matchCount: 5, | ||
| bonusMatch: false, | ||
| profit: 1500000, | ||
| }, | ||
| { | ||
| rank: 4, | ||
| matchCount: 4, | ||
| profit: 50000, | ||
| }, | ||
| { | ||
| rank: 5, | ||
| matchCount: 3, | ||
| profit: 5000, | ||
| }, | ||
| ]; | ||
|
Comment on lines
+1
to
+29
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. 오호! 저도 이런 데이터를 만들어놓고 시작해야겠어요! |
||
|
|
||
|
|
||
| export default LOTTO_RANKING_DATA; | ||
|
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. 일반 텍스트로 타입을 구분한 것과 Symbol 을 사용해서 구분하는 것의 차이점이 무엇인가요...?! 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. 오오 독립성을 보장해준다? 'lottoTicket' === 'lottoTicket' // true
Symbol('lottoTicket') === Symbol('lottoTicket') // false |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| const LOTTO_TYPE = { | ||
| TICKET: Symbol('lottoTicket'), | ||
| WINNING: Symbol('winningLotto'), | ||
| }; | ||
|
|
||
| export default LOTTO_TYPE; |
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.
중복을 줄이는 용도로 팩토리 메서드를 만들어도 괜찮을듯합니다!