Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: woowacourse-precourse/javascript-racingcar-6
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: main
Choose a base ref
...
head repository: Hys-Lee/javascript-racingcar-6
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: main
Choose a head ref
Able to merge. These branches can be automatically merged.
  • 16 commits
  • 5 files changed
  • 1 contributor

Commits on Oct 30, 2023

  1. Copy the full SHA
    641407b View commit details
  2. Copy the full SHA
    0719ce5 View commit details
  3. Feat: handling a input for car names

    made function seperateCarNames from utils/inputHandling.js
    for checking valid car names
    Hys-Lee committed Oct 30, 2023
    Copy the full SHA
    904a1f6 View commit details
  4. Feat: input handling for trial number

    checked whether input is integer greater and equal than 0
    it would throw error for execption cases.
    
    get trial number as private property because it will only used in App class
    
    get car names as public property for now.
    it could be changed to private one.
    Hys-Lee committed Oct 30, 2023
    Copy the full SHA
    2c4575b View commit details
  5. Feat: made class for cars

    it has 2 properties, which are name and the number of movements
    when the random number is greater and equal than 4 represented as the number of dash.
    
    it also has 2 methods, which are for getting random number and checking movements
    and printing all dashes of the current car.
    Hys-Lee committed Oct 30, 2023
    Copy the full SHA
    df10473 View commit details
  6. Copy the full SHA
    f10cf3a View commit details
  7. Feat: filter and get winners who have the highest number of movement

    resulting and other steps are seperated into methods.
    
    got the maximum number of movements from all cars and comparing all cars
    to find one having maximum movements.
    Hys-Lee committed Oct 30, 2023
    Copy the full SHA
    1efd43d View commit details
  8. Feat: printing winners

    also changed class Car's property, totalMovementDashArray, from private to public
    because App.js need all the properties of each Car's instances to yield Maximum number of movements.
    
    and updated README.md
    fisnished to make features except testing.
    
    I forgot to commit above changes just because this developing is pretty faster than I predict
    after sophisticately making README.md.
    
    I would change previous commits by rebase.
    Hys-Lee committed Oct 30, 2023
    Copy the full SHA
    b545b90 View commit details

Commits on Oct 31, 2023

  1. Style: added aid comment for exception on car name

    noted for considering a zero-length name case.
    Hys-Lee committed Oct 31, 2023
    Copy the full SHA
    ab14b25 View commit details
  2. Test: input test for car name

    for considering only "," as seperator
    if there are other characters, they would be considered characters for car name
    Hys-Lee committed Oct 31, 2023
    Copy the full SHA
    754561c View commit details
  3. Test: input test for trial number

    considered error case that the trial input value is not integer
    also, deleted testing valid greater than 100 for trial number
    because it doesn't need to split it from just testing integer
    also, deleted unused helper function
    Hys-Lee committed Oct 31, 2023
    Copy the full SHA
    1473fa3 View commit details
  4. Fix: added blank with ',' between winnders for output

    if not using join function, there no blank between winners.
    Hys-Lee committed Oct 31, 2023
    Copy the full SHA
    b4abba3 View commit details
  5. Test: output test for ordinary, one winner case

    for only printing one winner, which is ordinary and standard case
    Hys-Lee committed Oct 31, 2023
    Copy the full SHA
    6782261 View commit details
  6. Test: output test for ordinary, multi-winners case

    for checking form connecting winners with ", "
    Hys-Lee committed Oct 31, 2023
    Copy the full SHA
    f05ecd7 View commit details
  7. Test: output test for when trial number is 0

    with 0 trial, all cars are at the same position,
    which means all of them are winners
    Hys-Lee committed Oct 31, 2023
    Copy the full SHA
    128840a View commit details
  8. Style: removed comments, fix test name for trial number

    it doesn't need comments because of test name
    Hys-Lee committed Oct 31, 2023
    Copy the full SHA
    0d0b851 View commit details
Showing with 270 additions and 1 deletion.
  1. +125 −0 __tests__/myTest.js
  2. +26 −0 classes/Car.js
  3. +41 −0 docs/README.md
  4. +53 −1 src/App.js
  5. +25 −0 utils/inputHandling.js
125 changes: 125 additions & 0 deletions __tests__/myTest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import App from '../src/App';
import { MissionUtils } from '@woowacourse/mission-utils';

const mockQuestions = (inputs) => {
MissionUtils.Console.readLineAsync = jest.fn();
MissionUtils.Console.readLineAsync.mockImplementation(() => {
const input = inputs.shift();
return Promise.resolve(input);
});
};
const mockRandoms = (numbers) => {
MissionUtils.Random.pickNumberInRange = jest.fn();
numbers.reduce((acc, number) => {
return acc.mockReturnValueOnce(number);
}, MissionUtils.Random.pickNumberInRange);
};

const getLogSpy = () => {
const logSpy = jest.spyOn(MissionUtils.Console, 'print');
logSpy.mockClear();
return logSpy;
};
const MOVING_FORWARD = 4;
const STOP = 3;
describe('입력 테스트', () => {
test('자동차 이름 5자 이하, 구분자는 ","만 - 통과', async () => {
const randoms = [MOVING_FORWARD, STOP];
const inputs = ['it/is,two', '1'];
const outputs = ['최종 우승자 : it/is'];
const logSpy = getLogSpy();

mockQuestions(inputs);
mockRandoms([...randoms]);
const app = new App();

await app.play();
outputs.forEach((output) => {
expect(logSpy).toHaveBeenCalledWith(expect.stringContaining(output));
});
});
test('자동차 이름 5자 이하, 구분자는 ","만 - 오류', async () => {
const randoms = [MOVING_FORWARD];
const inputs = ['it/is/not/valid', '1'];

mockQuestions(inputs);
mockRandoms([...randoms]);
const app = new App();
await expect(app.play()).rejects.toThrow('[ERROR]');
});

test('시도할 횟수 입력 0이상 정수 - 통과', async () => {
const randoms = [MOVING_FORWARD, STOP, MOVING_FORWARD];
const inputs = ['int', '3'];
const outputs = ['최종 우승자 : int'];
const logSpy = getLogSpy();

mockQuestions(inputs);
mockRandoms([...randoms]);
const app = new App();

await app.play();
outputs.forEach((output) => {
expect(logSpy).toHaveBeenCalledWith(expect.stringContaining(output));
});
});
test.each([[['float', '3.5']], [['str', 'asd']], [['minus', '-6']]])(
'도할 횟수 입력 0이상 정수 - 오류',
async (inputs) => {
const randoms = [MOVING_FORWARD, STOP, MOVING_FORWARD];

mockQuestions(inputs);
mockRandoms([...randoms]);
const app = new App();
await expect(app.play()).rejects.toThrow('[ERROR]');
},
);
});

describe('출력 테스트', () => {
test('우승자가 혼자일 때', async () => {
const randoms = [MOVING_FORWARD, STOP];
const inputs = ['one,two', '1'];
const outputs = ['최종 우승자 : one'];
const logSpy = getLogSpy();

mockQuestions(inputs);
mockRandoms([...randoms]);
const app = new App();

await app.play();
outputs.forEach((output) => {
expect(logSpy).toHaveBeenCalledWith(expect.stringContaining(output));
});
});
test('우승자가 여럿일 때 콤마 확인', async () => {
const randoms = [MOVING_FORWARD, MOVING_FORWARD];
const inputs = ['one,two', '1'];
const outputs = ['최종 우승자 : one, two'];
const logSpy = getLogSpy();

mockQuestions(inputs);
mockRandoms([...randoms]);
const app = new App();

await app.play();
outputs.forEach((output) => {
expect(logSpy).toHaveBeenCalledWith(expect.stringContaining(output));
});
});
test('우승자가 여럿일 때 콤마 확인', async () => {
const randoms = [MOVING_FORWARD, MOVING_FORWARD];
const inputs = ['one,two', '0'];
const outputs = ['최종 우승자 : one, two'];
const logSpy = getLogSpy();

mockQuestions(inputs);
mockRandoms([...randoms]);
const app = new App();

await app.play();
outputs.forEach((output) => {
expect(logSpy).toHaveBeenCalledWith(expect.stringContaining(output));
});
});
});
26 changes: 26 additions & 0 deletions classes/Car.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { MissionUtils } from '@woowacourse/mission-utils';

const HURDLE = 4;
export default class Car {
name;
totalMovementDashArray;

constructor(name) {
this.name = name;
this.totalMovementDashArray = [];
}

tryToMove() {
const randomNum = MissionUtils.Random.pickNumberInRange(0, 9);
if (randomNum >= HURDLE) {
this.totalMovementDashArray.push('-');
}
}
print() {
const dashes = this.totalMovementDashArray.reduce(
(acc, cur) => `${acc}${cur}`,
'',
);
MissionUtils.Console.print(`${this.name} : ${dashes}`);
}
}
41 changes: 41 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# 구현할 기능 목록

1. [✔️] 자동차 이름 입력 받기
1-1. [✔️] 5자 이하 체크 (쉼표가 없다면 자동차 구분 없음)
1-2. [✔️] 쉼표 구분해 자동차 이름 구별

2. [✔️] 시도할 횟수 입력 받기
2-1. [✔️] Number 타입 체크
2-2. [✔️] 0이상 정수 체크

3. [✔️] 자동차 객체화 하기
3-1. [✔️] 자동차 클래스 생성
3-2. [✔️] 각 차수 별 0~9 무작위 값 생성
3-3. [✔️] 전진하는 조건 (4이상) 설정
3-4. [✔️] 각 차수 별 전진 여부 저장

4. [✔️] 게임 총괄하기
4-1. [✔️] 시도 횟수 카운팅하기 (시도 횟수만큼 반복하도록)

5. [✔️] 모든 자동차 객체 관리하기
5-1. [✔️] 경주할 모든 자동차 객체 담은 배열 생성
5-2. [✔️] 자동차 객체들의 총 전진 횟수 각각 체크
5-3. [✔️] 가장 높은 전진 횟수 가진 객체 이름 업데이트

6. [✔️] 출력 관리하기
6-1. [✔️] 자동차 이름 입력 및 시도 횟수 입력을 위한 안내문 출력
6-2. [✔️] 각 차수마다(무작위 값 반영 이후) 모든 자동차 객체들의 총 전진 횟수 체크 및 형식따라 출력
6-3. [✔️] 최종 우승자 (가장 높은 전진 횟수 가진 객체들 이름) 출력

7. [✔️] 예외 출력 관리하기
7-1. [✔️] 경주할 자동차 이름 예외, 길이 및 구분자 확인 요구
7-2. [✔️] 시도 횟수 타입 예외, 0 이상의 정수 입력 요구

8. [✔️] 테스트 구현하기
**8-1. 입력 값 예외 테스트**
8-1-1. [✔️] 자동차 이름 길이 5자 이상, 미만
8-1-2. [✔️] 시도할 횟수 입력 0이상 정수, 그 이외 (소수,음수,문자)
**8-2. 출력 값 테스트**
8-2-1. [✔️] 우승자가 한 명일 경우 일반적 출력 체크
8-2-2. [✔️] 우승자가 여러명일 경우 쉼표 구분자 이용 체크
8-2-3. [✔️] 시도할 횟수 0일 때 모두 우승인지 체크
54 changes: 53 additions & 1 deletion src/App.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,57 @@
import { MissionUtils } from '@woowacourse/mission-utils';
import { seperateCarNames, processTrialInput } from '../utils/inputHandling.js';
import Car from '../classes/Car.js';

class App {
async play() {}
carNamesArray;
carList;
#trialNum;
constructor() {
this.carNamesArray = [];
this.carList = [];
this.#trialNum = 0;
}

async init() {
this.carNamesArray = seperateCarNames(
await MissionUtils.Console.readLineAsync(
'경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)\n',
),
);
this.carList = this.carNamesArray.map((name) => new Car(name));
this.#trialNum = processTrialInput(
await MissionUtils.Console.readLineAsync('시도할 횟수는 몇 회인가요?\n'),
);
}

running() {
MissionUtils.Console.print('\n실행 결과');
for (let i = 0; i < this.#trialNum; i++) {
this.carList.forEach((car) => {
car.tryToMove();
car.print();
});
MissionUtils.Console.print('');
}
}

resulting() {
const movementNumsForEachCar = this.carList.map(
(car) => car.totalMovementDashArray.length,
);
const maxMovementNum = Math.max(...movementNumsForEachCar);

const winners = this.carList
.filter((car) => car.totalMovementDashArray.length === maxMovementNum)
.map((car) => car.name)
.join(', ');
MissionUtils.Console.print(`최종 우승자 : ${winners}`);
}
async play() {
await this.init();
this.running();
this.resulting();
}
}

export default App;
25 changes: 25 additions & 0 deletions utils/inputHandling.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
export const seperateCarNames = (carNameString) => {
const result = carNameString.split(','); // 이름이 ''도 가능. 5자 이하면 되므로.
result.forEach((carName) => {
if (carName.length > 5) {
throw Error(
'[ERROR] 자동차 이름은 5자 이하, 각 이름은 쉼표(,)로 구분해주세요.',
);
}
});
return result;
};
export const processTrialInput = (inputString) => {
try {
const result = Number(inputString);
if (result < 0) {
throw Error('[ERROR] negative');
}
if (!Number.isInteger(result)) {
throw Error('[ERROR] float');
}
return result;
} catch (e) {
throw Error('[ERROR] Input a integer greater and equal than 0');
}
};