Skip to content
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

[로또] 이하연 미션 제출합니다. #625

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 3 additions & 4 deletions __tests__/ApplicationTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const runException = async (input) => {
// given
const logSpy = getLogSpy();

const RANDOM_NUMBERS_TO_END = [1,2,3,4,5,6];
const RANDOM_NUMBERS_TO_END = [1, 2, 3, 4, 5, 6];
const INPUT_NUMBERS_TO_END = ["1000", "1,2,3,4,5,6", "7"];

mockRandoms([RANDOM_NUMBERS_TO_END]);
Expand All @@ -40,12 +40,12 @@ const runException = async (input) => {

// then
expect(logSpy).toHaveBeenCalledWith(expect.stringContaining("[ERROR]"));
}
};

describe("로또 테스트", () => {
beforeEach(() => {
jest.restoreAllMocks();
})
});

test("기능 테스트", async () => {
// given
Expand Down Expand Up @@ -95,4 +95,3 @@ describe("로또 테스트", () => {
await runException("1000j");
});
});

13 changes: 11 additions & 2 deletions __tests__/LottoTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,20 @@ describe("로또 클래스 테스트", () => {
});

// TODO: 이 테스트가 통과할 수 있게 구현 코드 작성

test("로또 번호에 숫자가 아닌 값이 포함되어 있으면 예외가 발생한다.", () => {
expect(() => {
new Lotto([1, 2, 8, 4, 39, "&"]);
}).toThrow("[ERROR]");
});
test("로또 번호에 중복된 숫자가 있으면 예외가 발생한다.", () => {
expect(() => {
new Lotto([1, 2, 3, 4, 5, 5]);
}).toThrow("[ERROR]");
});

// 아래에 추가 테스트 작성 가능
test("로또 번호에 1~45 사이의 값이 아닌 값이 포함되어 있으면 예외가 발생한다.", () => {
expect(() => {
new Lotto([1, 2, 3, 4, 39, 48]);
}).toThrow("[ERROR]");
});
});
79 changes: 78 additions & 1 deletion src/App.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,82 @@
import { MissionUtils } from "@woowacourse/mission-utils";
import { LottoRandom } from "./LottoRandom";
import Lotto from "./Lotto";

class App {
async play() {}
async play() {
let lotto_price = await this.getIncomeAndCheck();
let lotto_num = lotto_price / 1000;

MissionUtils.Console.print(`${lotto_num}개를 구매했습니다.`);

const lottoArray = new LottoRandom(lotto_num);
lottoArray.printLottoSet();
// 보너스 번호를 입력 받는다.
let real_num = await this.getRealLottoNumber();
let bonus = await MissionUtils.Console.readLineAsync(
"보너스 번호를 입력해 주세요."
);
lottoArray.getPrize(real_num, bonus);
lottoArray.getResult();
this.printReturnRate(lottoArray.win, lotto_price);
}

//[x]구입 금액은 1,000원 단위로 입력 받으며 1,000원으로 나누어 떨어지지 않는 경우 예외 처리한다.
async getIncomeAndCheck() {
let income_num;
while (true) {
try {
let income = await MissionUtils.Console.readLineAsync(
"구입금액을 입력해 주세요."
);
income_num = Number(income);
if (isNaN(income_num))
throw new Error("[ERROR] 숫자가 잘못된 형식입니다.");
if (income_num % 1000 != 0)
throw new Error("[ERROR] 구입 금액은 1,000원 단위로 입력해주세요.");
break;
} catch (error) {
MissionUtils.Console.print(error.message);
}
}
return income_num;
}

async getRealLottoNumber() {
let real_number, real_number_arr;
while (true) {
real_number = await MissionUtils.Console.readLineAsync(
"\n당첨 번호를 입력해 주세요.\n"
);
if (real_number) {
//[x] 당첨 번호를 입력 받는다. 번호는 쉼표(,)를 기준으로 구분한다.
real_number_arr = real_number.split(",");
real_number_arr = real_number_arr.map((e) => Number(e)); // 숫자로 변환

try {
new Lotto(real_number_arr);
break;
} catch (error) {
MissionUtils.Console.print(error.message);
}
} else {
MissionUtils.Console.print("[ERROR] 당첨 번호를 입력해주세요.");
}
}
return real_number_arr;
}

// [x] 수익률은 소수점 둘째 자리에서 반올림한다
printReturnRate(prize, num) {
let all_prize =
prize[0] * 5000 +
prize[1] * 50000 +
prize[2] * 1500000 +
prize[3] * 30000000 +
prize[4] * 2000000000;
let rate = ((100 * all_prize) / num).toFixed(1);
MissionUtils.Console.print(`총 수익률은 ${rate}%입니다.`);
}
}

export default App;
39 changes: 36 additions & 3 deletions src/Lotto.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,51 @@
class Lotto {
import { MissionUtils } from "@woowacourse/mission-utils";

export class Lotto {
#numbers;

constructor(numbers) {
this.#validate(numbers);
if (new Set(numbers).size !== numbers.length) {
throw new Error("[ERROR] 당첨 번호엔 중복이 없어야 합니다.");
}
for (let num of numbers) {
if (typeof num != "number")
throw new Error("[ERROR] 당첨 값은 숫자로만 구성되어 있어야 합니다.");
if (num > 45 || num < 1) {
throw new Error("[ERROR] 당첨 번호는 1에서 45의 숫자여야 합니다.");
}
}
this.#numbers = numbers;
}

#validate(numbers) {
if (numbers.length !== 6) {
if (!numbers || !Array.isArray(numbers) || numbers.length !== 6) {
throw new Error("[ERROR] 로또 번호는 6개여야 합니다.");
}
}

// TODO: 추가 기능 구현
printAllLottoNum() {
let arr = this.#numbers.sort((a, b) => a - b);
let formatted_arr = `[${arr.join(", ")}]`;
MissionUtils.Console.print(formatted_arr);
}

countWin(arr) {
let win = 0;
for (let i = 0; i < 6; i++) {
if (this.#numbers.includes(arr[i])) {
win++;
}
}
return win;
}

getUserLotto(bonus) {
if (this.#numbers.includes(bonus)) {
return true;
}
return false;
}
}

export default Lotto;
66 changes: 66 additions & 0 deletions src/LottoRandom.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { MissionUtils } from "@woowacourse/mission-utils";
import { Lotto } from "./Lotto.js";

export class LottoRandom {
constructor(lotto_num) {
this.num = lotto_num;
this.lotto_value_arr = [];
this.makeAllLottoSet(this.num);
this.win = new Array(5).fill(0);
}
makeAllLottoSet() {
for (let i = 0; i < this.num; i++) {
let one = this.makeOneLottoSet();
this.lotto_value_arr.push(one);
}
}

makeOneLottoSet() {
let one_lotto = MissionUtils.Random.pickUniqueNumbersInRange(1, 45, 6);
one_lotto = new Lotto(one_lotto);
return one_lotto;
}

printLottoSet() {
for (let lotto of this.lotto_value_arr) {
lotto.printAllLottoNum();
}
}

getPrize(win, bonus) {
for (let i = 0; i < this.num; i++) {
let isWin = this.lotto_value_arr[i].countWin(win);
let isBonus = this.lotto_value_arr[i].getUserLotto(bonus);
this.calculatePrize(isWin, isBonus);
}
}

calculatePrize(isWin, isBonus) {
if (isWin === 3) {
this.win[0]++;
}
if (isWin === 4) {
this.win[1]++;
}
if (isWin === 5 && isBonus == false) {
this.win[2]++;
}
if (isWin === 5 && isBonus == true) {
this.win[3]++;
}
if (isWin === 6) {
this.win[4]++;
}
}
// / 결과 출력
getResult() {
MissionUtils.Console.print("\n당첨 통계\n___");
MissionUtils.Console.print(`3개 일치 (5,000원) - ${this.win[0]}개`);
MissionUtils.Console.print(`4개 일치 (50,000원) - ${this.win[1]}개`);
MissionUtils.Console.print(`5개 일치 (1,500,000원) - ${this.win[2]}개`);
MissionUtils.Console.print(
`5개 일치, 보너스 볼 일치 (30,000,000원) - ${this.win[3]}개`
);
MissionUtils.Console.print(`6개 일치 (2,000,000,000원) - ${this.win[4]}개`);
}
}