diff --git a/app.js b/app.js new file mode 100644 index 0000000..874a42e --- /dev/null +++ b/app.js @@ -0,0 +1,68 @@ +const todos = require('./todos.js'); + +const readline = require('readline').createInterface({ + input: process.stdin, + output: process.stdout +}); + +const getCmdList = (command) => { + const regexpForSeperateCommand = /[^\$]+/g; + return command.match(regexpForSeperateCommand); +}; + +const executeCommand = (commandArr) => { + + if (arguments.length != 1) return; + + if (commandArr.length == 2) { + todos[commandArr[0]](commandArr[1]); + } else if (commandArr.length == 3) { + todos[commandArr[0]](commandArr[1], commandArr[2]); + } +}; + +const isValidCommand = (command, obj) => { + let result = false; + if (Object.keys(obj).includes(command)) result = true; + return result; +} + +const delay = (time) => { + return new Promise(function(resolve, reject){ + setTimeout(resolve, time); + }); +} + +const runProgram = (readline) => { + + readline.setPrompt('명령하세요: '); + readline.prompt(); + readline.on('line', (userInput) => { + + try { + const commandArr = getCmdList(userInput); + const primaryCommand = commandArr[0]; + + if (!isValidCommand(primaryCommand, todos)) { + console.log("올바르지 않은 명령어입니다") + readline.prompt(); + } + + delay(0) + .then(() => {executeCommand(commandArr); return delay(0)}) + .then(() => {if (primaryCommand != 'show') return delay(2000)}) + .then(() => {if (primaryCommand == 'update') return delay(2500)}) + .then(() => {readline.prompt(); return delay(0)}) + + } catch (error) { + console.log("명령어를 다시 입력해주세요") + readline.prompt(); + } + + }).on('close', () => { + console.log("프로그램을 종료합니다."); + process.exit(); + }); +} + +runProgram(readline); \ No newline at end of file diff --git a/oop/app.js b/oop/app.js new file mode 100644 index 0000000..1e4a4fa --- /dev/null +++ b/oop/app.js @@ -0,0 +1,54 @@ +const readLine = require('readline').createInterface( { + input:process.stdin, + output:process.stdout, +}); +const CommandParser = require('./commandParser.js'); +const Utils = require('./utils.js'); +const Instruction = require('./instruction.js'); +const ExceptionHandling = require('./exceptionHandling.js'); + +function Program() { + this.cmdArr = ['show','delete','update','add']; +} + +Program.prototype = { + + runProgram : (readline, cmdArr) => { + readline.setPrompt('명령하세요: '); + readline.prompt(); + readline.on('line', (userInput) => { + + try { + + if (!ExceptionHandling.prototype.isValidSeperator(userInput)) {ExceptionHandling.prototype.missingSeperatorException();} + const cmdList = CommandParser.prototype.getCmdList(userInput); + + if (!CommandParser.prototype.isValidCommand(cmdList[0], cmdArr)) {ExceptionHandling.prototype.CommandMissingException();} + + CommandParser.prototype.executeCmd(cmdList); + + Utils.prototype.delay(0) + .then(() => {if (cmdList[0] === 'update') return Utils.prototype.delay(3500);}) + .then(() => {return Utils.prototype.delay(1000);}) + .then(() => {if (cmdList[0] !== 'show') Instruction.prototype.show('all');}) + .catch(function(e) {console.log(e);}) + .then(() => {readLine.prompt();}); + + } catch(e) { + console.error(e.message); + readLine.prompt(); + } + + }).on('close', () => { + console.log("프로그램을 종료합니다."); + process.exit(); + }); + } + +}; + + +const run = (() => { + const program = new Program(); + program.runProgram(readLine, program.cmdArr); +})(); \ No newline at end of file diff --git a/oop/commandParser.js b/oop/commandParser.js new file mode 100644 index 0000000..21f0ea1 --- /dev/null +++ b/oop/commandParser.js @@ -0,0 +1,39 @@ +const Instruction = require('./instruction.js'); +const ExceptionHandling = require('./exceptionHandling.js'); + +function CommandParser () { + +} + +CommandParser.prototype = { + + getCmdList : (input) => { + const regexp = /[^\$]+/g; + return input.match(regexp); + }, + + executeCmd : (command) => { + try { + + if (command.length === 2) { + Instruction.prototype[command[0]](command[1]); + } else if (command.length === 3) { + Instruction.prototype[command[0]](command[1], command[2]); + } else { + ExceptionHandling.prototype.CommandMissingException(); + } + + } catch (e) { + console.error(e.message); + return; + } + }, + + isValidCommand : (command, arr) => { + let result = false; + if (arr.includes(command)) result = true; + return result; + }, +}; + +module.exports = CommandParser; diff --git a/oop/exceptionHandling.js b/oop/exceptionHandling.js new file mode 100644 index 0000000..16be549 --- /dev/null +++ b/oop/exceptionHandling.js @@ -0,0 +1,30 @@ +function CustomException() { + +} + +CustomException.prototype = { + + missingSeperatorException : () => { + throw new Error("구분자 $가 존재하지 않습니다"); + }, + notExistIdException : () => { + throw new Error(`찾으시는 id가 존재하지 않습니다`); + }, + sameStatusException : () => { + throw new Error(`같은 상태로 업데이트 할 수 없습니다`); + }, + CommandMissingException : () => { + throw new Error(`올바른 명령어가 아닙니다`); + }, + + isValidSeperator : (input) => { + let result = true; + const regexp = /\$/g; + if (input.match(regexp) == null) result = false; + + return result; + } + +}; + +module.exports = CustomException; \ No newline at end of file diff --git a/oop/instruction.js b/oop/instruction.js new file mode 100644 index 0000000..897f645 --- /dev/null +++ b/oop/instruction.js @@ -0,0 +1,90 @@ +const originData = require('./todosdata.json'); +const convertedData = JSON.parse(JSON.stringify(originData)).data; +const Utils = require('./utils.js'); +const ExceptionHandling = require('./exceptionHandling.js'); + +function Instruction() { + +} + +Instruction.prototype = { + + show: (status) => { + const statusArr = ['all', 'todo', 'doing', 'done']; + + if (status === 'all') { + let [numOfTodos, numOfDoings, numOfDones] = [0, 0, 0]; + + convertedData.forEach((value) => { + + if (value.status === 'todo') numOfTodos++; + else if (value.status === 'doing') numOfDoings++; + else if (value.status === 'done') numOfDones++; + + }); + + console.log(`현재상태 : todo: ${numOfTodos}개, doing: ${numOfDoings}개, done: ${numOfDones}개`); + + } else if (statusArr.includes(status)) { + const tasks = Utils.prototype.getArrByCondition(convertedData, (val) => { + return (status === val.status); + }); + let message = `${status}리스트 총 ${tasks.length}건 : `; + tasks.forEach(obj => { + message += `'${obj.name}, ${obj.id}번,' `; + }); + + console.log(message); + } + }, + + add: (name, tags) => { + const id = Utils.prototype.getRadomId(99999, 1); + let obj = { + name, + tags, + status: 'todo', + id, + }; + convertedData.push(obj); + const message = `${obj.name} 1개가 추가됐습니다.(id : ${obj.id})`; + console.log(message); + }, + + delete : (id) => { + const targetObj = Utils.prototype.getArrByCondition(convertedData, (val) => { return id == val.id;})[0]; + + try { + if (!targetObj) ExceptionHandling.prototype.notExistIdException(); + } catch (e) { + console.error(e.message); + return; + } + + convertedData.splice(convertedData.indexOf(targetObj), 1); + let message = `${targetObj.name}이 ${targetObj.status}에서 삭제되었습니다.`; + console.log(message); + + }, + + update :(id, status) => { + const targetObj = Utils.prototype.getArrByCondition(convertedData, (val) => { return id == val.id;})[0]; + try { + if (!targetObj) ExceptionHandling.prototype.notExistIdException(); + if (targetObj.status === status) ExceptionHandling.prototype.sameStatusException(); + } catch (e) { + console.error(e.message); + return; + } + + targetObj.status = status; + + const message = `${targetObj.name}가 ${targetObj.status}로 상태가 변경되었습니다`; + + setTimeout(() => { + console.log(message); + }, 3000); + }, +}; + +module.exports = Instruction; \ No newline at end of file diff --git a/oop/todosData.json b/oop/todosData.json new file mode 100644 index 0000000..282d7ba --- /dev/null +++ b/oop/todosData.json @@ -0,0 +1,23 @@ +{ + "result" : true, + "data": [ + { + "name" : "자바스크립트 공부하기", + "tags" : ["programming", "javascript"], + "status" : "todo", + "id" : 123 + }, + { + "name" : "그림 그리기", + "tags" : ["picture", "favorite"], + "status" : "doing", + "id" : 312323 + }, + { + "name" : "파이썬 공부하기", + "tags" : ["programming", "javascript"], + "status" : "done", + "id" : 213232 + } + ] +} \ No newline at end of file diff --git a/oop/utils.js b/oop/utils.js new file mode 100644 index 0000000..d5b5b05 --- /dev/null +++ b/oop/utils.js @@ -0,0 +1,25 @@ +function Utils () { + +} + +Utils.prototype = { + + getArrByCondition : (arr, condition) => { + return arr.reduce((acc, val) => { + if (condition(val)) acc.push(val); + return acc; + }, []); + }, + + getRadomId : (max, min) => { + Math.floor(Math.random() * (max-min)) + 1; + }, + + delay : (time) => { + return new Promise(function(resolve, reject){ + setTimeout(resolve, time); + }); + }, +}; + +module.exports = Utils; \ No newline at end of file diff --git a/todos.js b/todos.js new file mode 100644 index 0000000..796ed1d --- /dev/null +++ b/todos.js @@ -0,0 +1,88 @@ +//todos.js +const originData = require('./todosList.json'); +const convertedData = JSON.parse(JSON.stringify(originData)).data; +const idGenerator = (max, min) => Math.floor(Math.random() * (max - min)) + 1; + +const getArrByCondition = (arr, condition) => { + return arr.reduce((acc, val) => { + if (condition(val)) acc.push(val); + return acc; + }, []); +}; + +const showStatusLazy = () => { + setTimeout(() => { + showData('all'); + }, 1000); +} + +const isDuplicated = (val, key, convertedData) => { + let result = false; + convertedData.forEach((element) => { + if (val === element[key]) result = true; + }) + return result; +} + +const showData = (type) => { + if (type === 'all') { + const numOfTodos = getArrByCondition(convertedData, (val) => {return val.status === "todo"}).length; + const numOfDoings = getArrByCondition(convertedData, (val) => {return val.status === "doing"}).length; + const numOfDones = getArrByCondition(convertedData, (val) => {return val.status === "done"}).length; + + console.log(`현재상태 : todo: ${numOfTodos}개, doing: ${numOfDoings}개, done: ${numOfDones}개`); + + } else { + const objArr = getArrByCondition(convertedData, (val) => {return (type === val.status)}); + let result = `${type} 리스트 : 총${objArr.length}건 :`; + getArrByCondition(objArr, (val) => {result += `, '${val.name}, ${val.id}번'`; return true}); + console.log(`${result}`); + } +} + +const addData = (name, tags) => { + const id = idGenerator(99999, 1); + + if (isDuplicated(id, "id", convertedData)) { + return addData(name, tags); + } + + let obj = { + name, + tags, + status: 'todo', + id, + }; + + convertedData.push(obj); + console.log(`${obj.name} 1개가 추가됐습니다.(id : ${obj.id})`); + showStatusLazy(); +} + +const deleteData = (id)=> { + const target = getArrByCondition(convertedData, (val) => {return val.id === id})[0]; + if (!target) {console.log('일치하는 id가 없습니다'); return;} + + convertedData.splice(convertedData.indexOf(target), 1); + console.log(`${target.name} ${target.status}가 목록에서 삭제됐습니다.`); + showStatusLazy(); +}; + +const updateData = (id, status)=> { + const target = getArrByCondition(convertedData, (val) => {return val.id === id})[0]; + if (!target) {console.log('일치하는 id가 없습니다'); return;} + + target.status = status; + + setTimeout(() => { + console.log(`${target.name}가 ${status}로 상태가 변경되었습니다`); + showStatusLazy(); + }, 3000); +} + +module.exports = { + "show" : showData, + "add" : addData, + "update" : updateData, + "delete" : deleteData, +}; \ No newline at end of file diff --git a/todosList.json b/todosList.json new file mode 100644 index 0000000..1734fe5 --- /dev/null +++ b/todosList.json @@ -0,0 +1,41 @@ +{ + "result" : true, + "data": [ + { + "name" : "자바스크립트 공부하기", + "tags" : ["programming", "javascript"], + "status" : "todo", + "id" : 12123123 + }, + { + "name" : "그림 그리기", + "tags" : ["picture", "favorite"], + "status" : "doing", + "id" : 123 + }, + { + "name" : "파이썬 공부하기", + "tags" : ["programming", "javascript"], + "status" : "done", + "id" : 213232 + }, + { + "name" : "자바 공부하기", + "tags" : ["programming", "java"], + "status" : "todo", + "id" : 123345 + }, + { + "name" : "음악 듣기", + "tags" : ["music", "favorite"], + "status" : "doing", + "id" : 12123 + }, + { + "name" : "정규식 공부하기", + "tags" : ["programming", "RegExp"], + "status" : "done", + "id" : 1234 + } + ] +}