-
Notifications
You must be signed in to change notification settings - Fork 172
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[1단계 - 자동차 경주 구현] 가브리엘(윤주현) 미션 제출합니다. (#153)
* chore: npm 모듈 설치 - @woowacourse/mission-utils 설치 * docs: 요구사항 문서 작성 * docs: 프리코스 피드백 및 페어프로그래밍 규칙 작성 * chore: 불필요한 npm 모듈 삭제 * feat: 입출력 담당 모듈 구현 * feat: n대의 자동차를 입력 받는 기능 구현 Co-authored-by: Gabriel Ju Hyun, Yoon <gabrielyoon7@gmail.com> * feat: 각 자동차 이름이 1자 이상 5자 이하의 글자인지 판별하는 기능 구현 * test: 각 자동차 이름이 1자 이상 5자 이하의 글자인지 판별하는 기능 테스트 * feat: 자동차 생성 기능 구현 * feat: 시도 횟수를 입력 받는 기능 구현 * feat: 시도 횟수를 입력이 자연수인지 판별하는 기능 구현 * test: 시도 횟수를 입력이 자연수인지 판별하는 기능 테스트 * feat: 입력받은 시도 횟수 만큼 모든 자동차의 이동을 시도하는 기능 구현 * feat: 0부터 9까지 랜덤으로 숫자를 발생시키는 기능 구현 * feat: 차가 전진하는 기능 구현 * feat: 자동차의 현재 이동 상태를 출력하는 기능 구현 * feat: 최종 우승자를 판별하고 출력하는 기능 구현 * docs: 기능목록 최신화 * feat: 잘못된 이름 입력이 들어왔을 경우 에러 처리 구현 Co-authored-by: Gabriel Ju Hyun, Yoon <gabrielyoon7@gmail.com> * feat: 잘못된 횟수 입력이 들어왔을 경우 에러 처리 구현 * feat: 게임 종료 후 cleanup 기능 구현 * test: 자동차 이름 유효성 검사 테스트 케이스 추가 * test: 시도 횟수 검사 테스트 케이스 추가 * refactor: 콜백 패턴의 입력 로직을 async/await로 변경 Co-authored-by: Gabriel Ju Hyun, Yoon <gabrielyoon7@gmail.com> * refactor: 형 변환 책임 분리 * refactor: 게임 동작/제어에 관한 책임 분리 - 원래 콜백패턴에서 사용해 의존성이 입력 로직에 얽혀있었는데, play 메서드로 이동했다. * refactor: UI 출력을 담당하는 로직을 분리 * refactor: 콘솔을 담당하는 책임 분리 * style: 비구조화 할당 문법으로 변경 * refactor: 문자열 리터럴 상수화 * refactor: 불필요한 필드 삭제 - 일회성으로 사용한 tryCount를 제거 * refactor: 사용하지 않는 import 문 삭제 * refactor: 자동차 생성 로직 분리 * refactor: 메서드에서 필드로 사용하던 변수를 매개변수로 변경 * refactor: 불필요한 import 문 제거 * test: Car 클래스 테스트 작성 * test: 테스트를 위한 형변환 로직 추가 * chore: eslint 설정 변경 * test: 랜덤 기능 mock 함수 생성 * test: 전진할지 안할지 판단하는 기능 테스트 * fix: mocking 이 안되는 이슈 해결 * test: 승자들을 판단하는 기능 테스트 * chore: lint 설정 변경 * docs: 요구사항 문서 작성 * chore: yarn 삭제 * docs: 기능 요구사항 개선 * refactor: 랜덤 생성한 숫자가 4 이상인 경우 이동하는 로직 개선 - 자동차가 아닌, 게임 매니저가 판단하도록 개선 * refactor: 함수명 변경 - tryMoveCars => raceCars * refactor: for i 를 forEach로 변경 * refactor: this.#cars에 대한 정보를 클래스에서 직접 참조하도록 변경 * refactor: 자동차 출력 메소드 로직 개선 * refactor: pickRandomNumber로직 개선 * refactor: 메시지를 상수로 관리하는 파일 위치 및 파일명 변경 * refactor: 메세지 값 상수화 추가 * refactor: 차를 설정해주는 메소드가 차량 객체를 저장하도록 개선 * fix: 테스트 케이스 오류 수정 - description을 이해할 수 있는 표현으로 수정 - 로직 수정으로 인한 테스트케이스 fail을 해결 --------- Co-authored-by: 2yunseong <dbsdltjd3701@naver.com>
- Loading branch information
1 parent
51fbb02
commit 8208397
Showing
17 changed files
with
8,953 additions
and
3,987 deletions.
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
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,16 @@ | ||
/* eslint-disable max-lines-per-function */ | ||
/* eslint-disable no-undef */ | ||
const Car = require('../src/Car'); | ||
|
||
describe('Car Test', () => { | ||
test.each([ | ||
['yun', 12, 12, true], | ||
['ga', 10, 11, false], | ||
])('자동차 전진 검사', (name, go, position, expected) => { | ||
const car = new Car(name); | ||
for (let i = 0; i < go; i++) { | ||
car.move(true); | ||
} | ||
expect(car.getPosition() === position).toBe(expected); | ||
}); | ||
}); |
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,56 @@ | ||
/* eslint-disable max-lines-per-function */ | ||
/* eslint-disable no-undef */ | ||
// const Car = require('../src/Car'); | ||
const GameManager = require('../src/GameManager'); | ||
const RandomGenerator = require('../src/utils/RandomGenerator'); | ||
|
||
const mockRandom = (number) => { | ||
RandomGenerator.pickRandomNumber = jest.fn(); | ||
RandomGenerator.pickRandomNumber.mockReturnValueOnce(number); | ||
}; | ||
|
||
const mockRandoms = (numbers) => { | ||
RandomGenerator.pickRandomNumber = jest.fn(); | ||
numbers.reduce((acc, number) => { | ||
return acc.mockReturnValueOnce(number); | ||
}, RandomGenerator.pickRandomNumber); | ||
}; | ||
|
||
describe('GameManager Test', () => { | ||
test('Random mock Test', () => { | ||
mockRandom(10); | ||
expect(RandomGenerator.pickRandomNumber()).toBe(10); | ||
}); | ||
|
||
test.each([ | ||
[9, true], | ||
[4, true], | ||
[3, false], | ||
[0, false], | ||
])('특정 숫자가 전진이 가능한 값인지를 판별하는 함수 : %i', (number, expected) => { | ||
mockRandom(number); | ||
const gameManager = new GameManager(); | ||
expect(gameManager.isForward()).toEqual(expected); | ||
}); | ||
|
||
test.each([ | ||
[['yun', 'park', 'kim'], [9, 0, 1, 8, 1, 2, 7, 5, 6], ['yun']], | ||
[ | ||
['choi', 'ann', 'lee', 'gabi'], | ||
[0, 0, 5, 5, 0, 0, 9, 9], | ||
['lee', 'gabi'], | ||
], | ||
[ | ||
['aa', 'bb'], | ||
[0, 0, 5, 5, 0, 0, 9, 9], | ||
['aa', 'bb'], | ||
], | ||
])('승자를 판별하는 테스트 (%#)', (carNames, moves, winners) => { | ||
const gameManager = new GameManager(); | ||
const cars = gameManager.generateCars(carNames); | ||
mockRandoms(moves); | ||
gameManager.setCars(cars); | ||
gameManager.raceCars(moves.length/cars.length); | ||
expect(gameManager.judgeWinners()).toEqual(winners); | ||
}); | ||
}); |
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,28 @@ | ||
/* eslint-disable max-lines-per-function */ | ||
/* eslint-disable no-undef */ | ||
const { isValidCarNames, isValidTryCount } = require('../src/utils/Validation'); | ||
|
||
describe('Validation Test', () => { | ||
test.each([ | ||
[['yunseong', 'gabriel'], false], | ||
[['aa', 'bb', 'cc'], true], | ||
[['aa', 'bb', ''], false], | ||
// [['aa', 'bb', '윤생이😁😁'], true], => 고민할 부분(서로게이트 쌍) | ||
])('이름 유효성 검사(%s: %s)', (names, expected) => { | ||
expect(isValidCarNames(names)).toBe(expected); | ||
}); | ||
|
||
test.each([ | ||
['-1', false], | ||
['0', false], | ||
['5', true], | ||
['34.55', false], | ||
['10,000', false], | ||
['string134', false], | ||
['aa', false], | ||
['13n', false], | ||
['', false], | ||
])('시도 횟수가 자연수 인가?(%s : %s)', (tryCount, expected) => { | ||
expect(isValidTryCount(+tryCount)).toBe(expected); | ||
}); | ||
}); |
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,52 @@ | ||
# 🚗 자동차 경주 | ||
|
||
## 🔎 프리코스 피드백(참고용) | ||
|
||
### 1주차 | ||
- 요구사항을 정확히 준수한다 | ||
- 커밋 메시지를 의미 있게 작성한다 | ||
- git을 통해 관리할 자원에 대해서도 고려한다 | ||
- Pull Request를 보내기 전 브랜치를 확인한다 | ||
- PR을 한 번 작성했다면 닫지 말고 추가 커밋을 한다 | ||
- 이름을 통해 의도를 드러낸다 | ||
- 축약하지 않는다 | ||
- 공백도 코딩 컨벤션이다 | ||
- 공백 라인을 의미 있게 사용한다 | ||
- space와 tab을 혼용하지 않는다 | ||
- 의미 없는 주석을 달지 않는다 | ||
- linter와 Code Formatter의 기능을 활용한다 | ||
- EOL(End Of Line) | ||
- 불필요한 console.log를 남기지 않는다 | ||
- JavaScript에서 제공하는 API를 적극 활용한다 | ||
|
||
|
||
### 2주차 | ||
- README.md를 상세히 작성한다 | ||
- 기능 목록을 재검토한다 | ||
- 기능 목록을 업데이트한다 | ||
- 값을 하드 코딩하지 않는다 | ||
- 구현 순서도 코딩 컨벤션이다 | ||
- 한 함수가 한 가지 기능만 담당하게 한다 | ||
- 함수가 한 가지 기능을 하는지 확인하는 기준을 세운다 | ||
- JavaScript에서 객체를 만드는 다양한 방법을 이해하고 사용한다. | ||
- 테스트를 작성하는 이유에 대해 본인의 경험을 토대로 정리해본다 | ||
- 처음부터 큰 단위의 테스트를 만들지 않는다 | ||
|
||
|
||
### 3주차 | ||
- 함수(메서드) 라인에 대한 기준 | ||
- 발생할 수 있는 예외 상황에 대해 고민한다 | ||
- 비즈니스 로직과 UI 로직을 분리한다 | ||
- 객체의 상태 접근을 제한한다 | ||
- 객체는 객체스럽게 사용한다 | ||
- 필드의 수를 줄이기 위해 노력한다 | ||
- 성공하는 케이스 뿐만 아니라 예외에 대한 케이스도 테스트한다 | ||
- 테스트 코드도 코드다 | ||
- 테스트를 위한 코드는 구현 코드에서 분리되어야 한다 | ||
- 단위 테스트하기 어려운 코드를 단위 테스트하기 | ||
|
||
## 💛 페어 프로그래밍 규칙 | ||
- 네비게이터와 드라이버는 요구사항 1개 완료시 변경한다. | ||
- 모든 작업은 정규 시간 안에 끝낸다. 미련이 남아도 생각만 해온다. | ||
- 쉬고 싶으면 쉬고싶다고 편하게 말한다. | ||
- 의견을 자유롭게 내는데 주저하지 말자. |
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,51 @@ | ||
# 자동차 경주 요구사항 | ||
|
||
## 기능 요구사항 | ||
|
||
- [x] 주어진 횟수 동안 n 대의 자동차는 전진 또는 멈출 수 있다. | ||
- [x] 자동차에 이름을 부여할 수 있다. | ||
- [x] 전진하는 자동차를 출력할 때 자동차 이름을 같이 출력한다. | ||
- [x] 자동차 이름은 쉼표(,)를 기준으로 구분한다. | ||
- [x] 자동차 이름은 5자 이하만 가능하다. | ||
- [x] 사용자는 몇 번의 이동을 할 것인지를 입력할 수 있어야 한다. | ||
- [x] 전진하는 조건은 0에서 9 사이에서 무작위 값을 구한 후 무작위 값이 4 이상일 경우이다. | ||
- [x] 자동차 경주 게임을 완료한 후 누가 우승했는지를 알려준다. | ||
- [x] 우승자는 한 명 이상일 수 있다. | ||
- [x] 우승자가 여러 명일 경우 쉼표(,)를 이용하여 구분한다. | ||
- [x] 사용자가 잘못된 입력 값을 작성한 경우 에러 메시지를 보여주고, 다시 입력할 수 있게 한다. | ||
- [x] n대의 자동차를 입력 받을 수 있다. | ||
- [x] 사용자의 이동 횟수 입력을 자연수인지 판별한다. | ||
- [x] 각 자동차 이름이 1자 이상 5자 이하의 글자인지 판별한다. | ||
- [x] 최종 우승자의 이름을 출력한다. | ||
- [x] 최종 우승자를 판별한다. | ||
- [x] 입력받은 시도 횟수 만큼 모든 자동차의 이동을 시도한다. | ||
- [x] 자동차가 이동할지 시도한다. | ||
- [x] 모든 자동차의 현재 이동 상태를 출력한다. | ||
- [x] 자동차의 현재 이동 상태를 출력한다. | ||
- [x] 입력받은 이름을 기반으로 자동차들을 생성한다. | ||
- [x] 입출력을 받게 하는 모듈을 구현한다. | ||
- [x] 자동차 객체를 자동차 이름과 위치 상태를 갖도록 구현한다. | ||
- [x] 0부터 9까지 랜덤으로 숫자를 발생시킨다. | ||
|
||
## 프로그래밍 요구사항 | ||
- [x] 코드 스타일 가이드에 따라 컨벤션을 준수하며 개발한다. | ||
- [x] 변수 선언시 var를 사용하지 않는다. let, const를 사용한다. | ||
- [x] 전역 변수를 만들지 않는다. | ||
- [x] 축약하지 않는다. | ||
- [x] 하드 코딩된 값 대신에 의미 있는 상수를 활용한다. | ||
- [x] 동등 연산자는 `===`로만 사용한다. | ||
- [x] 함수(또는 메서드)의 길이가 10라인을 넘어가지 않도록 구현한다. | ||
- [x] 함수(또는 메서드)가 한 가지 일만 하도록 만든다. | ||
- [x] 함수(또는 메서드)의 들여쓰기 depth는 2단계까지만 허용한다. | ||
- 예를 들어 while문 안에 if문이 있으면 depth는 2단계 이다. | ||
- 힌트) 함수(또는 메서드) 분리는 들여쓰기 depth를 줄이는 좋은 방법이다. | ||
- [x] else 예약어를 쓰지 않는다. | ||
- [x] 도메인 로직과 UI 로직을 분리한다. | ||
- [x] 모든 도메인 로직에 단위 테스트를 구현한다. (UI 로직은 제외) | ||
|
||
## 과제 진행 요구사항 | ||
|
||
### 기능 목록 및 commit 로그 요구사항 | ||
|
||
- [x] 기능을 구현하기 전에 `docs/REQUIREMENTS.md` 파일에 구현할 기능 목록을 정리해 추가한다. | ||
- [x] git의 commit 단위는 앞 단계에서 `REQUIREMENTS.md` 파일에 정리한 기능 목록 단위로 추가한다. |
Oops, something went wrong.