diff --git a/README.md b/README.md index 13420b29..1841bd66 100644 --- a/README.md +++ b/README.md @@ -1 +1,61 @@ -# javascript-calculator-precourse \ No newline at end of file +# javascript-calculator-precourse + +## 기능 + +- [x] "덧셈할 문자열을 입력해 주세요." 출력 + +- [x] 입력받기 + +- [x] 입력값이 0인지 확인 + + 입력값이 비었을 경우 결과값 0으로 처리 + +- [x] 커스텀 구분자 사용시 + + 1. 커스텀 시작 구분자("//"), 커스텀 종료 구분자("\n")가 잘못 표기시에 예외상황 발생 + 2. 입력 문자열이 "//"로 시작하고 "\n"끝났을 경우 커스텀 구분자 추출 + 3. 커스텀 구분자를 구분자 배열에 추가 + 4. 커스텀 구분자가 존재하지 않을시 기본구분자 사용 + +- [x] 기본 구분자 사용 시 + + 1. 구분자(쉼표, 콜론, 커스텀 구분자)가 잘못 표기시에 예외상황 발생 + 2. 기본 구분자 마저 존재하지 않을시 예외 발생 + 3. 구분자(쉼표, 콜론, 커스텀 구분자)를 기준으로 분리 + +- [x] 나뉜 문자열을 숫자 배열로 변환 (빈 문자열 제외) + + 숫자가 아닌 문자가 포함된 경우 예외 발생 + +- [x] 숫자 배열의 모든 값을 합산 + +- [x] "결과 : ${결과값}" 출력 + +- [x] 프로그램 종료 + +## 입력방식 조건 + +정상 입력 형식은 다음 예시와 같다: + +- "1,2,3" → 쉼표(,) 구분 +- "1,2:3" → 쉼표(,)와 콜론(:) 혼용 +- "//;\n1;2;3" → 커스텀 구분자 세미콜론(;) +- "//;\n1;2:3" → 커스텀 구분자와 기본 구분자(:) 혼용 + +위의 형식을 제외한 모든 입력은 예외로 처리한다. + +## 예외 처리시 + +"[ERROR]"로 시작하는 메시지와 함께 Error를 발생시킨 후 애플리케이션은 종료되어야 한다. + +## 만났던 오류 + +- 폴더 및 파일 이름 대소문자 불일치로 인한 import 오류
+ 파일명을 PromptOutput에서 promptOutput 변경하였습니다
이유는 FSD 환경에서는 PascalCase도 가능하지만, + 현재 프로젝트는 React/TypeScript 환경이 아니므로 camelCase로 통일 + +## 아쉬운점 + +상수사용, enum, 사용하지 못한 점 +파일명에 대한 아쉬움 +함수를 더 쪼갤 수 있었을 것 같다는 것에 대한 아쉬움 diff --git a/src/App.js b/src/App.js index 091aa0a5..ce8eab95 100644 --- a/src/App.js +++ b/src/App.js @@ -1,5 +1,9 @@ +import { calculator } from "./page/index.js"; + class App { - async run() {} + async run() { + await calculator(); + } } export default App; diff --git a/src/entities/delimiter/index.js b/src/entities/delimiter/index.js new file mode 100644 index 00000000..fb768c8e --- /dev/null +++ b/src/entities/delimiter/index.js @@ -0,0 +1 @@ +export { Delimiters } from "./model/delimiters.js"; diff --git a/src/entities/delimiter/model/delimiters.js b/src/entities/delimiter/model/delimiters.js new file mode 100644 index 00000000..3eb50d64 --- /dev/null +++ b/src/entities/delimiter/model/delimiters.js @@ -0,0 +1,15 @@ +export class Delimiters { + constructor() { + this.delimiterArray = [",", ":"]; + } + + addCustumDelimiter(elimiter) { + if (!this.delimiterArray.includes(elimiter)) { + this.delimiterArray.push(elimiter); + } + } + + getDelimiterArray() { + return this.delimiterArray; + } +} diff --git a/src/entities/number/index.js b/src/entities/number/index.js new file mode 100644 index 00000000..b3d8207b --- /dev/null +++ b/src/entities/number/index.js @@ -0,0 +1 @@ +export { NumberArray } from "./model/numberArray.js"; diff --git a/src/entities/number/model/numberArray.js b/src/entities/number/model/numberArray.js new file mode 100644 index 00000000..b2fa100a --- /dev/null +++ b/src/entities/number/model/numberArray.js @@ -0,0 +1,23 @@ +export class NumberArray { + constructor() { + this.numberArray = []; + } + + isNumber(number) { + return Number.isInteger(Number(number)) && Number(number) >= 0; + } + + addNumber(number) { + this.numberArray.push(Number(number)); + } + + getArray() { + return this.numberArray; + } + getSum() { + return this.numberArray.reduce( + (acc, curr) => Number(acc) + Number(curr), + 0 + ); + } +} diff --git a/src/features/checkDelimiter/index.js b/src/features/checkDelimiter/index.js new file mode 100644 index 00000000..a606e809 --- /dev/null +++ b/src/features/checkDelimiter/index.js @@ -0,0 +1 @@ +export { parseCustomDelimiter } from "./parseCustomDelimiter/parseCustomDelimiter.js"; diff --git a/src/features/checkDelimiter/parseCustomDelimiter/parseCustomDelimiter.js b/src/features/checkDelimiter/parseCustomDelimiter/parseCustomDelimiter.js new file mode 100644 index 00000000..35bb930d --- /dev/null +++ b/src/features/checkDelimiter/parseCustomDelimiter/parseCustomDelimiter.js @@ -0,0 +1,28 @@ +import { Delimiters } from "../../../entities/delimiter/index.js"; +import { customError } from "../../../shared/error/index.js"; + +export function parseCustomDelimiter(input) { + const startMarker = input.indexOf("//"); + const endMarker = input.indexOf("\\n"); + + const delimiterManager = new Delimiters(); + let inputString = input; + + if ( + (startMarker === -1 && endMarker !== -1) || + (startMarker === 0 && endMarker === -1) + ) { + customError(); + } + + if (startMarker === 0 && endMarker !== -1) { + const customDelimiter = input.slice(startMarker + 2, endMarker - 1); + delimiterManager.addCustumDelimiter(customDelimiter); + inputString = input.slice(endMarker + 2); + } + + return { + DelimiterArray: delimiterManager.getDelimiterArray(), + Input: inputString, + }; +} diff --git a/src/features/input/index.js b/src/features/input/index.js new file mode 100644 index 00000000..85e6195b --- /dev/null +++ b/src/features/input/index.js @@ -0,0 +1 @@ +export { readInput } from "./readInput/readInput.js"; diff --git a/src/features/input/readInput/readInput.js b/src/features/input/readInput/readInput.js new file mode 100644 index 00000000..b0db3c36 --- /dev/null +++ b/src/features/input/readInput/readInput.js @@ -0,0 +1,6 @@ +import { Console } from "@woowacourse/mission-utils"; + +export async function readInput() { + const input = await Console.readLineAsync(""); + return input; +} diff --git a/src/features/output/index.js b/src/features/output/index.js new file mode 100644 index 00000000..3210d1ac --- /dev/null +++ b/src/features/output/index.js @@ -0,0 +1,2 @@ +export { promptOutput } from "./promptOutput/promptOutput.js"; +export { resultOutput } from "./resultOutput/resultOutput.js"; diff --git a/src/features/output/promptOutput/PromptOutput.js b/src/features/output/promptOutput/PromptOutput.js new file mode 100644 index 00000000..ba717035 --- /dev/null +++ b/src/features/output/promptOutput/PromptOutput.js @@ -0,0 +1,4 @@ +import { Console } from "@woowacourse/mission-utils"; +export async function promptOutput() { + Console.print("덧셈할 문자열을 입력해 주세요."); +} diff --git a/src/features/output/resultOutput/resultOutput.js b/src/features/output/resultOutput/resultOutput.js new file mode 100644 index 00000000..09904289 --- /dev/null +++ b/src/features/output/resultOutput/resultOutput.js @@ -0,0 +1,5 @@ +import { Console } from "@woowacourse/mission-utils"; + +export function resultOutput(sum) { + Console.print(`결과 : ${sum}`); +} diff --git a/src/features/splitInput/index.js b/src/features/splitInput/index.js new file mode 100644 index 00000000..97888684 --- /dev/null +++ b/src/features/splitInput/index.js @@ -0,0 +1 @@ +export { splitInput } from "./splitInput/splitInput.js"; diff --git a/src/features/splitInput/splitInput/splitInput.js b/src/features/splitInput/splitInput/splitInput.js new file mode 100644 index 00000000..67b4d128 --- /dev/null +++ b/src/features/splitInput/splitInput/splitInput.js @@ -0,0 +1,11 @@ +import { delimiterError } from "../../../shared/error/index.js"; + +export function splitInput(input, delimiterArray) { + if (!delimiterArray.some((delimiter) => input.includes(delimiter))) { + delimiterError(); + } + for (const delimiter of delimiterArray) { + input = input.replaceAll(delimiter, " "); + } + return input.split(" "); +} diff --git a/src/features/sumNumber/index.js b/src/features/sumNumber/index.js new file mode 100644 index 00000000..9d9b99d9 --- /dev/null +++ b/src/features/sumNumber/index.js @@ -0,0 +1 @@ +export { sumNumber } from "./sumNumber/sumNumber.js"; diff --git a/src/features/sumNumber/sumNumber/sumNumber.js b/src/features/sumNumber/sumNumber/sumNumber.js new file mode 100644 index 00000000..87057428 --- /dev/null +++ b/src/features/sumNumber/sumNumber/sumNumber.js @@ -0,0 +1,11 @@ +import { NumberArray } from "../../../entities/number/index.js"; +import { numberError } from "../../../shared/error/index.js"; + +export function sumNumber(numberArray) { + const array = new NumberArray(); + numberArray.forEach((number) => { + if (!array.isNumber(number)) numberError(); + array.addNumber(number); + }); + return array.getSum(); +} diff --git a/src/features/validate/index.js b/src/features/validate/index.js new file mode 100644 index 00000000..c0f1d98f --- /dev/null +++ b/src/features/validate/index.js @@ -0,0 +1 @@ +export { vaildateInput } from "./validateInput/validateInput.js"; diff --git a/src/features/validate/validateInput/lib/isEmpty.js b/src/features/validate/validateInput/lib/isEmpty.js new file mode 100644 index 00000000..38abc899 --- /dev/null +++ b/src/features/validate/validateInput/lib/isEmpty.js @@ -0,0 +1,4 @@ +export function isEmpty(input) { + if (input.trim() === "") return true; + return false; +} diff --git a/src/features/validate/validateInput/validateInput.js b/src/features/validate/validateInput/validateInput.js new file mode 100644 index 00000000..ac696538 --- /dev/null +++ b/src/features/validate/validateInput/validateInput.js @@ -0,0 +1,6 @@ +import { isEmpty } from "./lib/isEmpty.js"; + +export function vaildateInput(input) { + if (isEmpty(input)) return false; + return true; +} diff --git a/src/page/calculator/Calculator.js b/src/page/calculator/Calculator.js new file mode 100644 index 00000000..4858ce2a --- /dev/null +++ b/src/page/calculator/Calculator.js @@ -0,0 +1,24 @@ +import { parseCustomDelimiter } from "../../features/checkDelimiter/index.js"; +import { readInput } from "../../features/input/index.js"; +import { promptOutput, resultOutput } from "../../features/output/index.js"; +import { splitInput } from "../../features/splitInput/index.js"; +import { sumNumber } from "../../features/sumNumber/index.js"; +import { vaildateInput } from "../../features/validate/index.js"; +export async function calculator() { + await promptOutput(); + const input = await readInput(); + if (!vaildateInput(input)) { + resultOutput(0); + return; + } + const parsedInput = parseCustomDelimiter(input); + + const numbers = await splitInput( + parsedInput.Input, + parsedInput.DelimiterArray + ); + + const result = await sumNumber(numbers); + resultOutput(result); + return; +} diff --git a/src/page/index.js b/src/page/index.js new file mode 100644 index 00000000..71f7f030 --- /dev/null +++ b/src/page/index.js @@ -0,0 +1 @@ +export { calculator } from "./calculator/calculator.js"; diff --git a/src/shared/error/customError/customError.js b/src/shared/error/customError/customError.js new file mode 100644 index 00000000..4da30a1a --- /dev/null +++ b/src/shared/error/customError/customError.js @@ -0,0 +1,3 @@ +export function customError() { + throw new Error("[Error] : 커스텀 구분자 생성 실패"); +} diff --git a/src/shared/error/delimiterError/delimiterError.js b/src/shared/error/delimiterError/delimiterError.js new file mode 100644 index 00000000..f366fd1a --- /dev/null +++ b/src/shared/error/delimiterError/delimiterError.js @@ -0,0 +1,3 @@ +export function delimiterError() { + throw new Error("[Error] : 구분자는 쉼표(,) , 콜론(:) , 커스텀 입니다"); +} diff --git a/src/shared/error/index.js b/src/shared/error/index.js new file mode 100644 index 00000000..72e95286 --- /dev/null +++ b/src/shared/error/index.js @@ -0,0 +1,3 @@ +export { customError } from "./customError/customError.js"; +export { delimiterError } from "./delimiterError/delimiterError.js"; +export { numberError } from "./numberError/numberError.js"; diff --git a/src/shared/error/numberError/numberError.js b/src/shared/error/numberError/numberError.js new file mode 100644 index 00000000..d34934ef --- /dev/null +++ b/src/shared/error/numberError/numberError.js @@ -0,0 +1,3 @@ +export function numberError() { + throw new Error("[ERROR] : 정수만 입력 가능합니다"); +}