diff --git a/oop/.vscode/launch.json b/oop/.vscode/launch.json new file mode 100644 index 0000000..a053d23 --- /dev/null +++ b/oop/.vscode/launch.json @@ -0,0 +1,14 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "Launch Program", + "program": "${file}" + } + ] +} \ No newline at end of file diff --git a/oop/ErrorCheck.js b/oop/ErrorCheck.js new file mode 100644 index 0000000..42090cd --- /dev/null +++ b/oop/ErrorCheck.js @@ -0,0 +1,35 @@ +const todoList = require('./data.js'); + +const ErrorCheck = class { + syntaxError(input) { + let firstWord = input.match(/\w+/); + let seperator = input.match(/\$/g); + let zeroSeperator = (seperator===null); + if(zeroSeperator === true && !(firstWord[0] ==="undo" || firstWord[0] === "redo")) { + return false; + }else{ + let zeroSeperator = (firstWord[0] ==="undo" || firstWord[0] === "redo"); + let oneSeperator = ((firstWord[0] === "delete" || firstWord[0] === "show") && (seperator.length===1)); + let twoSeperator = ((firstWord[0] === "add" || firstWord[0] === "update") && (seperator.length===2)); + return zeroSeperator || oneSeperator || twoSeperator ? true : false; + } + + } + unknownIDError(ID) { + if(ID === NaN) { + return false; + } + return !(todoList.filter(v => v["id"] === ID).length === 0) ? true : false; + } + duplicatedStatusError(ID, status) { + return !(todoList.filter(v => v["id"] === ID)[0]["status"] === status) ? true : false; + } +} + + + + + +module.exports = { + ErrorCheck +} \ No newline at end of file diff --git a/oop/data.js b/oop/data.js new file mode 100644 index 0000000..48b47d8 --- /dev/null +++ b/oop/data.js @@ -0,0 +1,6 @@ +module.exports = [ + { 'name': 'asdf1', 'tag': [ 'asdf' ], 'status': 'todo', 'id': 9547 }, + { 'name': 'asdf2', 'tag': [ 'asdf' ], 'status': 'todo', 'id': 9546 }, + { 'name': 'asdf3', 'tag': [ 'asdf' ], 'status': 'todo', 'id': 9545 }, + { 'name': 'asdf4', 'tag': [ 'asdf' ], 'status': 'todo', 'id': 9544 } +]; \ No newline at end of file diff --git a/oop/errorMsg.js b/oop/errorMsg.js new file mode 100644 index 0000000..2203061 --- /dev/null +++ b/oop/errorMsg.js @@ -0,0 +1,6 @@ +module.exports = { + 'syntaxError' : "문법적으로 유효하지 않은 입력값입니다.", + 'unknownIDError' : "ID 사용이 잘못되었습니다.", + 'unknownID_duplicatedError' : "ID혹은 Status가 잘못되었습니다.", + 'ELSE_ERROR' : "치명적인 오류가 발생했습니다." +} \ No newline at end of file diff --git a/oop/my-todo-func.js b/oop/my-todo-func.js new file mode 100644 index 0000000..0a76672 --- /dev/null +++ b/oop/my-todo-func.js @@ -0,0 +1,253 @@ +const readline = require('readline'); +const todoList = require('./data.js'); +const errorCheck = require('./ErrorCheck.js'); +const errorMsg = require('./errorMsg.js'); +const todoPrint = require('./todoPrint.js'); + +const Error = new errorCheck.ErrorCheck(); +const Print = new todoPrint.ShowPrint(); + +const undoHistory = []; +const redoHistory = []; + + +let r = readline.createInterface({ + input:process.stdin, + output:process.stdout +}); + + +const todoForm = function (name, tag, status, id) { + this.name = name; + this.tag = [tag]; + this.status = status; + this.id = id; +} + +const HistoryForm = function (model, name, id, status, tag){ + this.model = model; + this.name = name; + this.id = id; + this.status = status; + this.tag = tag; + } + +const showAllTimer = (input) => { + setTimeout(todoCommonMethod.prototype.todoCount, input); + setTimeout(()=>{r.prompt()} , input+1000) +} + +const todoCommonMethod = class { + todoCount() { + let todo = todoList.filter(v => v.status === 'todo').length; + let doing = todoList.filter(v => v.status === 'doing').length; + let done = todoList.filter(v => v.status === 'done').length; + + Print.printShowAll(todo,doing,done); + } + + showElse(input) { + let temp = todoList.filter(v => v.status === input).map((obj)=>{ return ` '${obj.name}, ${obj.id}번'`}) + Print.printShowElse(temp.length, temp); + } + + makingID(){ + return Math.floor(Math.random() * 10000); + } + + findDataIdObj(input){ + let target = todoList.filter(v => v["id"] === input); + let targetName = target[0].name; + let targetIdx = todoList.indexOf(target[0]); + return [targetIdx, targetName]; + } +} + +const Redo = class { + dataInput(input) { + redoHistory.push(input); + } + makeUpdateHistory(status) { + undoHistory[undoHistory.length-1]['prev_status'] = status; + } + redoModel(model) { + let target = redoHistory[redoHistory.length-1]; + let [name, tag, status, id, prev_status] = [target['name'], target['tag'], target['status'], target['id'], target['prev_status']]; + + switch (model) { + case 'add' : + let newTodoList = new todoForm(name, tag[0], status, id); + todoList.push(newTodoList) + undoHistory.pop(); + break; + case 'update' : + todoModel.update(id, prev_status); + undoHistory.pop(); + break; + case 'delete' : + todoModel.delete(id, name, tag, status); + undoHistory.pop(); + break; + } + } +} +const redo = new Redo(); + +const Undo = class { + historyLengthCheck(form){ + if(undoHistory.length < 3) { + undoHistory.push(form); + } else { + undoHistory.shift(); + undoHistory.push(form); + } + } + + makeAddHistory(model, name, id, status, tag ){ + let historyForm = new HistoryForm(model, name, id, status, tag); + this.historyLengthCheck(historyForm) + } + + makeElseHistory(model, idx) { + let todoListData = todoList[idx] + let [name, tag, status, id] = [todoListData['name'], todoListData['tag'], todoListData['status'], todoListData['id']]; + let historyForm = new HistoryForm(model, name, id, status, tag ); + + this.historyLengthCheck(historyForm) + } + + undoModel(model) { + let target = undoHistory[undoHistory.length-1]; + let [name, tag, status, id] = [target['name'], target['tag'], target['status'], target['id']]; + + switch(model){ + case 'add' : + this.undoAdd(id); + break; + + case 'update' : + this.undoUpdate(id, status); + break; + + case 'delete' : + this.undoDelete(id, name, tag, status) + break; + } + } + + undoAdd(id) { + todoModel.delete(id) + undoHistory.pop(); + } + undoUpdate(id, status) { + todoModel.update(id, status) + undoHistory.pop(); + } + undoDelete(id, name, tag, status) { + let newTodoList = new todoForm(name, tag[0], status, id); + todoList.push(newTodoList) + } +} + +const undo = new Undo() + + +const TodoModel = class extends todoCommonMethod{ + show(input) { + let status = input[0]; + status === 'all' ? this.todoCount() : this.showElse(status); + } + add(input) { + let [name, tag] = input; + let id = this.makingID(); + let newTodoList = new todoForm(name, tag, 'todo', id); + undo.makeAddHistory("add", name, id, 'todo', tag ); + + todoList.push(newTodoList); + + Print.printAdd(name,id); + showAllTimer(1000); + } + delete(id) { + let [targetIdx, targetName] = this.findDataIdObj(id) + undo.makeElseHistory('delete', targetIdx); + todoList.splice(targetIdx,1); + + Print.printDelete(targetName); + showAllTimer(1000); + } + update(id, status) { + let [targetIdx, targetName] = this.findDataIdObj(id) + undo.makeElseHistory('update', targetIdx); + todoList[targetIdx].status = status; + redo.makeUpdateHistory(status); + + + setTimeout(()=>{Print.printUpdate(targetName, status)}, 1000); + showAllTimer(4000); + } + +} + + +const todoModel = new TodoModel(); + + +const todoMain = (answer) => { + if(Error.syntaxError(answer) === false) { + Print.printError(errorMsg.syntaxError); + return true; + } + + let tempArr = answer.match(/\w+/g); + let action = tempArr.shift(0); + + if(action === "add") { + todoModel.add(tempArr); + + } else if(action === "delete") { + tempArr[0] = Number(tempArr[0]) + let ID = tempArr[0] + Error.unknownIDError(ID)==false ? Print.printError(errorMsg.unknownIDError) : todoModel.delete(ID); + + } else if(action === "update") { + tempArr[0] = Number(tempArr[0]) + let ID = tempArr[0] + let status = tempArr[1] + Error.unknownIDError(ID)==false || Error.duplicatedStatusError(ID,status)==false ? Print.printError(errorMsg.unknownID_duplicatedError) : todoModel.update(ID, status) + + } else if(action === "show") { + todoModel.show(tempArr); + + } else if(action === 'undo') { + undo.undoModel(undoHistory[undoHistory.length-1]['model']); + redoHistory.push(undoHistory[undoHistory.length-1]); + undoHistory.pop(); + + } else if(action === 'redo') { + redo.redoModel(redoHistory[redoHistory.length-1]['model']); + redoHistory.pop(); + + } else { + Print.printError(errorMsg.ELSE_ERROR); + } + +} + + + r.setPrompt('명령하세요 : '); + r.prompt(); + r.on('line', (line) => { + + if(line === 'exit') { + r.close(); + } + + if(todoMain(line)) { + r.prompt() + } + }) + + r.on('close', () => { + process.exit(); + }) \ No newline at end of file diff --git a/oop/todoPrint.js b/oop/todoPrint.js new file mode 100644 index 0000000..9b36317 --- /dev/null +++ b/oop/todoPrint.js @@ -0,0 +1,26 @@ +const ShowPrint = class { + printShowAll(todo, doing, done){ + console.log(`현재 상태 : todo: ${todo}개, doing: ${doing}개, done: ${done}개`) + } + printShowElse(temp_length, temp){ + console.log(`${this.value1}리스트 : 총 ${temp_length}건 : ${temp}`); + } + printAdd(name,id){ + console.log(`${name} 1개가 추가됐습니다. (id : ${id})`); + } + printUpdate(targetName, status){ + console.log(`${targetName} 가 ${status}상태로 변경되었습니다.`); + } + printDelete(targetName){ + console.log(`${targetName} 가 todo에서 삭제되었습니다.`) + } + printError(errorKey){ + console.log(errorKey) + } +} + + + +module.exports = { + ShowPrint +}