From 0ecd7c48b940cff595a96cec37e2c6c682d292bf Mon Sep 17 00:00:00 2001 From: Sei Kim Date: Mon, 19 Dec 2022 11:07:48 +0900 Subject: [PATCH 01/34] =?UTF-8?q?feat:=20CMError=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Git_ Exercise.xcodeproj/project.pbxproj | 4 +++ Git_ Exercise/Error.swift | 41 +++++++++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 Git_ Exercise/Error.swift diff --git a/Git_ Exercise.xcodeproj/project.pbxproj b/Git_ Exercise.xcodeproj/project.pbxproj index 424a5e0..2fa2fa4 100644 --- a/Git_ Exercise.xcodeproj/project.pbxproj +++ b/Git_ Exercise.xcodeproj/project.pbxproj @@ -8,6 +8,7 @@ /* Begin PBXBuildFile section */ 2768CA08294F453B00990B98 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2768CA07294F453B00990B98 /* main.swift */; }; + 40841A53294FFE1F00E540E4 /* Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40841A52294FFE1F00E540E4 /* Error.swift */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -25,6 +26,7 @@ /* Begin PBXFileReference section */ 2768CA04294F453B00990B98 /* Git_ Exercise */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "Git_ Exercise"; sourceTree = BUILT_PRODUCTS_DIR; }; 2768CA07294F453B00990B98 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; + 40841A52294FFE1F00E540E4 /* Error.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Error.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -58,6 +60,7 @@ isa = PBXGroup; children = ( 2768CA07294F453B00990B98 /* main.swift */, + 40841A52294FFE1F00E540E4 /* Error.swift */, ); path = "Git_ Exercise"; sourceTree = ""; @@ -120,6 +123,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 40841A53294FFE1F00E540E4 /* Error.swift in Sources */, 2768CA08294F453B00990B98 /* main.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Git_ Exercise/Error.swift b/Git_ Exercise/Error.swift new file mode 100644 index 0000000..5478ea8 --- /dev/null +++ b/Git_ Exercise/Error.swift @@ -0,0 +1,41 @@ +// +// Error.swift +// Git_ Exercise +// +// Created by sei_dev on 12/19/22. +// + +import Foundation + +//MARK: - CMError + +enum CMError: Error { + case invalidStartInput + case studentAleadyExists(name: String) + case studentNotFound(name: String) + case emptyCourse(name: String) + case courseNotFound(name: String, course:String) + case emptyStudents + case quitProgram +} + +extension CMError: LocalizedError { + public var errorDescription: String? { + switch self { + case .invalidStartInput: + return "입력이 잘못되었습니다. 1~5 사이의 숫자 혹은 X를 입력해주세요." + case let .studentAleadyExists(name): + return "\(name): 이미 존재하는 학생입니다. 추가하지 않습니다." + case let .studentNotFound(name): + return "\(name) 학생을 찾지 못했습니다." + case let .courseNotFound(name, course): + return "\(name) - \(course): 등록되지 않은 과목입니다." + case let .emptyCourse(name): + return "\(name): 등록된 과목이 없습니다." + case .emptyStudents: + return "등록된 학생이 존재하지 않습니다." + case .quitProgram: + return "프로그램을 종료합니다..." + } + } +} From 8b10008f1be0480197754084b427250bc760b4d0 Mon Sep 17 00:00:00 2001 From: Sei Kim Date: Mon, 19 Dec 2022 11:08:27 +0900 Subject: [PATCH 02/34] =?UTF-8?q?feat:=20IOError=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Git_ Exercise/Error.swift | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Git_ Exercise/Error.swift b/Git_ Exercise/Error.swift index 5478ea8..34f38f0 100644 --- a/Git_ Exercise/Error.swift +++ b/Git_ Exercise/Error.swift @@ -39,3 +39,18 @@ extension CMError: LocalizedError { } } } + +//MARK: - IOError + +enum IOError: Error { + case wrongInput +} + +extension IOError: LocalizedError { + public var errorDescription: String? { + switch self { + case .wrongInput: + return "입력이 잘못되었습니다. 다시 확인해주세요." + } + } +} From 5fd3cd9ebd2c01c664f7bcc850481b81f24838f7 Mon Sep 17 00:00:00 2001 From: Sei Kim Date: Mon, 19 Dec 2022 11:10:12 +0900 Subject: [PATCH 03/34] =?UTF-8?q?feat:=20IOManager=20-=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=EC=9E=90=20=EC=9E=85=EB=A0=A5=20=EB=B0=9B=EA=B8=B0=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Git_ Exercise.xcodeproj/project.pbxproj | 4 ++++ Git_ Exercise/IOManager.swift | 29 +++++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 Git_ Exercise/IOManager.swift diff --git a/Git_ Exercise.xcodeproj/project.pbxproj b/Git_ Exercise.xcodeproj/project.pbxproj index 2fa2fa4..87af2b5 100644 --- a/Git_ Exercise.xcodeproj/project.pbxproj +++ b/Git_ Exercise.xcodeproj/project.pbxproj @@ -9,6 +9,7 @@ /* Begin PBXBuildFile section */ 2768CA08294F453B00990B98 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2768CA07294F453B00990B98 /* main.swift */; }; 40841A53294FFE1F00E540E4 /* Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40841A52294FFE1F00E540E4 /* Error.swift */; }; + 40841A55294FFF5400E540E4 /* IOManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40841A54294FFF5300E540E4 /* IOManager.swift */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -27,6 +28,7 @@ 2768CA04294F453B00990B98 /* Git_ Exercise */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "Git_ Exercise"; sourceTree = BUILT_PRODUCTS_DIR; }; 2768CA07294F453B00990B98 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; 40841A52294FFE1F00E540E4 /* Error.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Error.swift; sourceTree = ""; }; + 40841A54294FFF5300E540E4 /* IOManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IOManager.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -61,6 +63,7 @@ children = ( 2768CA07294F453B00990B98 /* main.swift */, 40841A52294FFE1F00E540E4 /* Error.swift */, + 40841A54294FFF5300E540E4 /* IOManager.swift */, ); path = "Git_ Exercise"; sourceTree = ""; @@ -124,6 +127,7 @@ buildActionMask = 2147483647; files = ( 40841A53294FFE1F00E540E4 /* Error.swift in Sources */, + 40841A55294FFF5400E540E4 /* IOManager.swift in Sources */, 2768CA08294F453B00990B98 /* main.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Git_ Exercise/IOManager.swift b/Git_ Exercise/IOManager.swift new file mode 100644 index 0000000..b530e90 --- /dev/null +++ b/Git_ Exercise/IOManager.swift @@ -0,0 +1,29 @@ +// +// IOManager.swift +// Git_ Exercise +// +// Created by sei_dev on 12/19/22. +// + +import Foundation + +/// Console output type +enum OutputType { + case information + case reaction + case error +} + +enum IOManager { + static let nameRegex = "^[A-Za-z0-9_]+$" + + /// 사용자 입력 받기 + static func getInput(isStartStatus: Bool) throws -> String { + guard let input = readLine(), + input != "" else { + throw isStartStatus ? CMError.invalidStartInput : IOError.wrongInput + } + return input + } + +} From b93cad9f25fe101e8a6ef608b0418eb7cd6c4fef Mon Sep 17 00:00:00 2001 From: Sei Kim Date: Mon, 19 Dec 2022 11:13:23 +0900 Subject: [PATCH 04/34] =?UTF-8?q?feat:=20IOManager=20-=20=EC=9E=85?= =?UTF-8?q?=EB=A0=A5=20validity=20=ED=99=95=EC=9D=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Git_ Exercise/IOManager.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Git_ Exercise/IOManager.swift b/Git_ Exercise/IOManager.swift index b530e90..1203a09 100644 --- a/Git_ Exercise/IOManager.swift +++ b/Git_ Exercise/IOManager.swift @@ -26,4 +26,8 @@ enum IOManager { return input } + static func checkValidity(of str: String) -> Bool { + return str.range(of: Self.nameRegex, options: .regularExpression, range: nil, locale: nil) != nil + } + } From 4a2522194ca6ed0faa60db4c49c2e95e5258bbef Mon Sep 17 00:00:00 2001 From: Sei Kim Date: Mon, 19 Dec 2022 11:13:59 +0900 Subject: [PATCH 05/34] =?UTF-8?q?feat:=20IOManager=20-=20=EC=BD=98?= =?UTF-8?q?=EC=86=94=EC=97=90=20=EC=B6=9C=EB=A0=A5=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Git_ Exercise/IOManager.swift | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Git_ Exercise/IOManager.swift b/Git_ Exercise/IOManager.swift index 1203a09..d8ec114 100644 --- a/Git_ Exercise/IOManager.swift +++ b/Git_ Exercise/IOManager.swift @@ -30,4 +30,15 @@ enum IOManager { return str.range(of: Self.nameRegex, options: .regularExpression, range: nil, locale: nil) != nil } + /// message 콘솔에 출력 + static func writeMessage(_ message: String, type: OutputType = .information) { + switch type { + case .information: + print("> \(message)") + case .reaction: + print("< \(message)") + case .error: + fputs("⚠️ \(message)\n", stderr) + } + } } From 6a05462df5ac08fd2c49c1d5b36ae3f0308e41ab Mon Sep 17 00:00:00 2001 From: Sei Kim Date: Mon, 19 Dec 2022 11:17:07 +0900 Subject: [PATCH 06/34] =?UTF-8?q?feat:=20Info=20Message=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Git_ Exercise.xcodeproj/project.pbxproj | 4 +++ Git_ Exercise/Info.swift | 35 +++++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 Git_ Exercise/Info.swift diff --git a/Git_ Exercise.xcodeproj/project.pbxproj b/Git_ Exercise.xcodeproj/project.pbxproj index 87af2b5..6ae66b4 100644 --- a/Git_ Exercise.xcodeproj/project.pbxproj +++ b/Git_ Exercise.xcodeproj/project.pbxproj @@ -10,6 +10,7 @@ 2768CA08294F453B00990B98 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2768CA07294F453B00990B98 /* main.swift */; }; 40841A53294FFE1F00E540E4 /* Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40841A52294FFE1F00E540E4 /* Error.swift */; }; 40841A55294FFF5400E540E4 /* IOManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40841A54294FFF5300E540E4 /* IOManager.swift */; }; + 40841A572950008400E540E4 /* Info.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40841A562950008400E540E4 /* Info.swift */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -29,6 +30,7 @@ 2768CA07294F453B00990B98 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; 40841A52294FFE1F00E540E4 /* Error.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Error.swift; sourceTree = ""; }; 40841A54294FFF5300E540E4 /* IOManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IOManager.swift; sourceTree = ""; }; + 40841A562950008400E540E4 /* Info.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Info.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -64,6 +66,7 @@ 2768CA07294F453B00990B98 /* main.swift */, 40841A52294FFE1F00E540E4 /* Error.swift */, 40841A54294FFF5300E540E4 /* IOManager.swift */, + 40841A562950008400E540E4 /* Info.swift */, ); path = "Git_ Exercise"; sourceTree = ""; @@ -127,6 +130,7 @@ buildActionMask = 2147483647; files = ( 40841A53294FFE1F00E540E4 /* Error.swift in Sources */, + 40841A572950008400E540E4 /* Info.swift in Sources */, 40841A55294FFF5400E540E4 /* IOManager.swift in Sources */, 2768CA08294F453B00990B98 /* main.swift in Sources */, ); diff --git a/Git_ Exercise/Info.swift b/Git_ Exercise/Info.swift new file mode 100644 index 0000000..ff37604 --- /dev/null +++ b/Git_ Exercise/Info.swift @@ -0,0 +1,35 @@ +// +// Info.swift +// Git_ Exercise +// +// Created by sei_dev on 12/19/22. +// + +import Foundation + +struct Info { + static let start = "원하는 기능을 입력해주세요.\n" + static let methods = "1: 학생 추가, 2: 학생 삭제, 3: 성적 추가(변경), 4: 성적 삭제, 5: 평점 보기, X: 종료" + static let typeStudentNameToInsert = "추가할 학생의 이름을 입력해주세요." + static func addedStudent(name: String) -> String { + return "\(name) 학생을 추가했습니다." + } + static let typeStudentNameToDelete = "삭제할 학생의 이름을 입력해주세요." + static func deletedStudent(name: String) -> String { + return "\(name) 학생을 삭제했습니다." + } + static let addScoreInfo1 = "성적을 추가할 학생의 이름, 과목 이름, 성적(A+, A, F 등)을 띄어쓰기로 구분하여 차례로 작성해주세요.\n" + static let addScoreInfo2 = "입력 예) Mickey Swift A+\n" + static let addScoreInfo3 = "학생의 성적 중 해당 과목이 존재하면 기존 점수가 갱신됩니다." + static func addedScore(name:String, course: String, score: String) -> String { + return "\(name) 학생의 \(course) 과목이 \(score)로 추가(변경)되었습니다." + } + static let deleteScoreInfo1 = "성적을 삭제할 학생의 이름, 과목 이름을 띄어쓰기로 구분하여 차례로 작성해주세요.\n" + static let deleteScoreInfo2 = "입력 예) Mickey Swift" + static func deletedScore(name:String, course:String) -> String { + return "\(name) 학생의 \(course) 과목의 성적이 삭제되었습니다." + } + + static let typeStudentNameForAvg = "평점을 알고 싶은 학생의 이름을 입력해주세요." + static let exitProgram = "프로그램을 종료합니다..." +} From 0a398b40da00cc2352be04acbbf74e6db5bc97a0 Mon Sep 17 00:00:00 2001 From: Sei Kim Date: Mon, 19 Dec 2022 11:17:44 +0900 Subject: [PATCH 07/34] =?UTF-8?q?refactor:=20Info=20=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=ED=83=80=EC=9E=85=20enum=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit constant인 Info의 데이터타입을 struct에서 enum으로 변경 --- Git_ Exercise/Info.swift | 70 ++++++++++++++++++++++++++++------------ 1 file changed, 49 insertions(+), 21 deletions(-) diff --git a/Git_ Exercise/Info.swift b/Git_ Exercise/Info.swift index ff37604..77bfaea 100644 --- a/Git_ Exercise/Info.swift +++ b/Git_ Exercise/Info.swift @@ -7,29 +7,57 @@ import Foundation -struct Info { - static let start = "원하는 기능을 입력해주세요.\n" - static let methods = "1: 학생 추가, 2: 학생 삭제, 3: 성적 추가(변경), 4: 성적 삭제, 5: 평점 보기, X: 종료" - static let typeStudentNameToInsert = "추가할 학생의 이름을 입력해주세요." - static func addedStudent(name: String) -> String { - return "\(name) 학생을 추가했습니다." +enum Info { + static let start = """ + 원하는 기능을 입력해주세요. + 1: 학생 추가, 2: 학생 삭제, 3: 성적 추가(변경), 4: 성적 삭제, 5: 평점 보기, X: 종료 + """ + enum Student { + static let forAdd = "추가할 학생의 이름을 입력해주세요." + static func added(name: String) -> String { + return "\(name) 학생을 추가했습니다." + } + static let forDelete = "삭제할 학생의 이름을 입력해주세요." + static func deleted(name: String) -> String { + return "\(name) 학생을 삭제했습니다." + } } - static let typeStudentNameToDelete = "삭제할 학생의 이름을 입력해주세요." - static func deletedStudent(name: String) -> String { - return "\(name) 학생을 삭제했습니다." + enum Score { + static let forAdd = """ + 성적을 추가할 학생의 이름, 과목 이름, 성적(A+, A, F 등)을 띄어쓰기로 구분하여 차례로 작성해주세요. + 입력 예) Mickey Swift A+ + 학생의 성적 중 해당 과목이 존재하면 기존 점수가 갱신됩니다. + """ + static func added(name:String, course: String, score: String) -> String { + return "\(name) 학생의 \(course) 과목이 \(score)로 추가(변경)되었습니다." + } + static let forDelete = """ + 성적을 삭제할 학생의 이름, 과목 이름을 띄어쓰기로 구분하여 차례로 작성해주세요. + 입력 예) Mickey Swift + """ + static func deleted(name:String, course:String) -> String { + return "\(name) 학생의 \(course) 과목의 성적이 삭제되었습니다." + } + static let forAverage = "평점을 알고 싶은 학생의 이름을 입력해주세요." } - static let addScoreInfo1 = "성적을 추가할 학생의 이름, 과목 이름, 성적(A+, A, F 등)을 띄어쓰기로 구분하여 차례로 작성해주세요.\n" - static let addScoreInfo2 = "입력 예) Mickey Swift A+\n" - static let addScoreInfo3 = "학생의 성적 중 해당 과목이 존재하면 기존 점수가 갱신됩니다." - static func addedScore(name:String, course: String, score: String) -> String { - return "\(name) 학생의 \(course) 과목이 \(score)로 추가(변경)되었습니다." - } - static let deleteScoreInfo1 = "성적을 삭제할 학생의 이름, 과목 이름을 띄어쓰기로 구분하여 차례로 작성해주세요.\n" - static let deleteScoreInfo2 = "입력 예) Mickey Swift" - static func deletedScore(name:String, course:String) -> String { - return "\(name) 학생의 \(course) 과목의 성적이 삭제되었습니다." + enum Data { + static func saved(names: [String]) -> String { + return names.isEmpty ? "저장할 학생 정보가 없습니다." + : """ + 학생과 성적 정보를 성공적으로 저장했습니다. + 저장된 학생: \(names.joined(separator: ", ")) + """ + } + static func loaded(names: [String]) -> String { + return """ + 학생과 성적 정보를 성공적으로 불러왔습니다. + 불러온 학생: \(names.joined(separator: ", ")) + """ + } } - static let typeStudentNameForAvg = "평점을 알고 싶은 학생의 이름을 입력해주세요." - static let exitProgram = "프로그램을 종료합니다..." + enum Warning { + static let failedToLoadData = "기존의 Data를 불러오는 데 실패했습니다." + static let failedToLoadReaction = "실행 결과 안내 메세지를 불러오는 데 실패했습니다." + } } From 9e2b5ec7e4e2b138e3c719c6beed8f4b01f93c90 Mon Sep 17 00:00:00 2001 From: Sei Kim Date: Mon, 19 Dec 2022 11:22:13 +0900 Subject: [PATCH 08/34] =?UTF-8?q?feat:=20Status=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Git_ Exercise.xcodeproj/project.pbxproj | 4 ++++ Git_ Exercise/Status.swift | 21 +++++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 Git_ Exercise/Status.swift diff --git a/Git_ Exercise.xcodeproj/project.pbxproj b/Git_ Exercise.xcodeproj/project.pbxproj index 6ae66b4..5918140 100644 --- a/Git_ Exercise.xcodeproj/project.pbxproj +++ b/Git_ Exercise.xcodeproj/project.pbxproj @@ -11,6 +11,7 @@ 40841A53294FFE1F00E540E4 /* Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40841A52294FFE1F00E540E4 /* Error.swift */; }; 40841A55294FFF5400E540E4 /* IOManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40841A54294FFF5300E540E4 /* IOManager.swift */; }; 40841A572950008400E540E4 /* Info.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40841A562950008400E540E4 /* Info.swift */; }; + 40841A592950022400E540E4 /* Status.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40841A582950022400E540E4 /* Status.swift */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -31,6 +32,7 @@ 40841A52294FFE1F00E540E4 /* Error.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Error.swift; sourceTree = ""; }; 40841A54294FFF5300E540E4 /* IOManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IOManager.swift; sourceTree = ""; }; 40841A562950008400E540E4 /* Info.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Info.swift; sourceTree = ""; }; + 40841A582950022400E540E4 /* Status.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Status.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -67,6 +69,7 @@ 40841A52294FFE1F00E540E4 /* Error.swift */, 40841A54294FFF5300E540E4 /* IOManager.swift */, 40841A562950008400E540E4 /* Info.swift */, + 40841A582950022400E540E4 /* Status.swift */, ); path = "Git_ Exercise"; sourceTree = ""; @@ -130,6 +133,7 @@ buildActionMask = 2147483647; files = ( 40841A53294FFE1F00E540E4 /* Error.swift in Sources */, + 40841A592950022400E540E4 /* Status.swift in Sources */, 40841A572950008400E540E4 /* Info.swift in Sources */, 40841A55294FFF5400E540E4 /* IOManager.swift in Sources */, 2768CA08294F453B00990B98 /* main.swift in Sources */, diff --git a/Git_ Exercise/Status.swift b/Git_ Exercise/Status.swift new file mode 100644 index 0000000..27d03e5 --- /dev/null +++ b/Git_ Exercise/Status.swift @@ -0,0 +1,21 @@ +// +// Status.swift +// Git_ Exercise +// +// Created by sei_dev on 12/19/22. +// + +import Foundation + +typealias ParsedInput = [Codable] + +/// status 정보 +enum Status: String, Codable { + case start = "0" + case addStudent = "1" + case deleteStudent = "2" + case addScore = "3" + case deleteScore = "4" + case showScoreAverage = "5" + case exit = "X" +} From cb549a105a26e95fce7d8976d06e0d79031d4817 Mon Sep 17 00:00:00 2001 From: Sei Kim Date: Mon, 19 Dec 2022 11:22:47 +0900 Subject: [PATCH 09/34] =?UTF-8?q?feat:=20Status=20-=20infoMessage=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Git_ Exercise/Status.swift | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/Git_ Exercise/Status.swift b/Git_ Exercise/Status.swift index 27d03e5..f40111a 100644 --- a/Git_ Exercise/Status.swift +++ b/Git_ Exercise/Status.swift @@ -19,3 +19,26 @@ enum Status: String, Codable { case showScoreAverage = "5" case exit = "X" } + +//MARK: - Info Message + +extension Status { + var infoMessage: String { + switch self { + case .start: + return Info.start + case .addStudent: + return Info.Student.forAdd + case .deleteStudent: + return Info.Student.forDelete + case .addScore: + return Info.Score.forAdd + case .deleteScore: + return Info.Score.forDelete + case .showScoreAverage: + return Info.Score.forAverage + default: + return "" + } + } +} From 062ea8ab318c9db7dd8a9452c10dbe44fcb2ba95 Mon Sep 17 00:00:00 2001 From: Sei Kim Date: Mon, 19 Dec 2022 11:23:21 +0900 Subject: [PATCH 10/34] =?UTF-8?q?feat:=20Status=20-=20Result=20Message=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Git_ Exercise/Status.swift | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/Git_ Exercise/Status.swift b/Git_ Exercise/Status.swift index f40111a..2e256ec 100644 --- a/Git_ Exercise/Status.swift +++ b/Git_ Exercise/Status.swift @@ -42,3 +42,34 @@ extension Status { } } } + +//MARK: - Result Message + +extension Status { + func resMessage(input: ParsedInput) -> String? { + switch self { + case .addStudent: + if let name = input[0] as? String { + return Info.Student.added(name: name) + } + case .deleteStudent: + if let name = input[0] as? String { + return Info.Student.deleted(name: name) + } + case .addScore: + if let name = input[0] as? String, + let course = input[1] as? String, + let score = input[2] as? Score { + return Info.Score.added(name: name, course: course, score: score.description) + } + case .deleteScore: + if let name = input[0] as? String, + let course = input[1] as? String { + return Info.Score.deleted(name: name, course: course) + } + default: + return nil + } + return Info.Warning.failedToLoadReaction + } +} From 9efef18fdd2860b9e902f6aafe0884e5a1df95e0 Mon Sep 17 00:00:00 2001 From: Sei Kim Date: Mon, 19 Dec 2022 11:24:25 +0900 Subject: [PATCH 11/34] =?UTF-8?q?feat:=20Status=20-=20parse=20method=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Git_ Exercise/Status.swift | 39 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/Git_ Exercise/Status.swift b/Git_ Exercise/Status.swift index 2e256ec..5a332b1 100644 --- a/Git_ Exercise/Status.swift +++ b/Git_ Exercise/Status.swift @@ -73,3 +73,42 @@ extension Status { return Info.Warning.failedToLoadReaction } } + +//MARK: - Status - parse method + +extension Status { + /// status에 따라 사용자 입력 parse + func parse(input: String) -> ParsedInput? { + let splited = input.components(separatedBy: " ") + switch (self, splited.count) { + case (.start, 1): + guard let status = Status(rawValue: splited[0]) else { + return nil + } + return [status] + case (.addStudent, 1), (.deleteStudent, 1), (.showScoreAverage, 1): + guard IOManager.checkValidity(of: splited[0]) else { + return nil + } + return splited + case (.addScore, 3): + guard IOManager.checkValidity(of: splited[0]), + IOManager.checkValidity(of: splited[1]), + let score = Score(score: splited[2]) else { + return nil + } + var res = [Codable]() + res.append(contentsOf: splited) + res[2] = score + return res + case (.deleteScore, 2): + guard IOManager.checkValidity(of: splited[0]), + IOManager.checkValidity(of: splited[1]) else { + return nil + } + return splited + default: + return nil + } + } +} From 7775bf7a5d7492a44ba830a28ce3c7ee31ed2fbc Mon Sep 17 00:00:00 2001 From: Sei Kim Date: Mon, 19 Dec 2022 11:26:19 +0900 Subject: [PATCH 12/34] =?UTF-8?q?feat:=20Student=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Git_ Exercise.xcodeproj/project.pbxproj | 4 ++++ Git_ Exercise/Student.swift | 17 +++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 Git_ Exercise/Student.swift diff --git a/Git_ Exercise.xcodeproj/project.pbxproj b/Git_ Exercise.xcodeproj/project.pbxproj index 5918140..ddb56a8 100644 --- a/Git_ Exercise.xcodeproj/project.pbxproj +++ b/Git_ Exercise.xcodeproj/project.pbxproj @@ -12,6 +12,7 @@ 40841A55294FFF5400E540E4 /* IOManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40841A54294FFF5300E540E4 /* IOManager.swift */; }; 40841A572950008400E540E4 /* Info.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40841A562950008400E540E4 /* Info.swift */; }; 40841A592950022400E540E4 /* Status.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40841A582950022400E540E4 /* Status.swift */; }; + 40841A5B2950031B00E540E4 /* Student.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40841A5A2950031B00E540E4 /* Student.swift */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -33,6 +34,7 @@ 40841A54294FFF5300E540E4 /* IOManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IOManager.swift; sourceTree = ""; }; 40841A562950008400E540E4 /* Info.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Info.swift; sourceTree = ""; }; 40841A582950022400E540E4 /* Status.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Status.swift; sourceTree = ""; }; + 40841A5A2950031B00E540E4 /* Student.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Student.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -70,6 +72,7 @@ 40841A54294FFF5300E540E4 /* IOManager.swift */, 40841A562950008400E540E4 /* Info.swift */, 40841A582950022400E540E4 /* Status.swift */, + 40841A5A2950031B00E540E4 /* Student.swift */, ); path = "Git_ Exercise"; sourceTree = ""; @@ -133,6 +136,7 @@ buildActionMask = 2147483647; files = ( 40841A53294FFE1F00E540E4 /* Error.swift in Sources */, + 40841A5B2950031B00E540E4 /* Student.swift in Sources */, 40841A592950022400E540E4 /* Status.swift in Sources */, 40841A572950008400E540E4 /* Info.swift in Sources */, 40841A55294FFF5400E540E4 /* IOManager.swift in Sources */, diff --git a/Git_ Exercise/Student.swift b/Git_ Exercise/Student.swift new file mode 100644 index 0000000..c187902 --- /dev/null +++ b/Git_ Exercise/Student.swift @@ -0,0 +1,17 @@ +// +// Student.swift +// Git_ Exercise +// +// Created by sei_dev on 12/19/22. +// + +import Foundation + +final class Student: Codable { + let name: String + private(set) var scores = [String:Score]() + + init(name: String) { + self.name = name + } +} From ccb8d7f0799aa62cd713927227ffc82ae2ecd127 Mon Sep 17 00:00:00 2001 From: Sei Kim Date: Mon, 19 Dec 2022 11:26:34 +0900 Subject: [PATCH 13/34] =?UTF-8?q?feat:=20Student=20-=20isCourseEmpty=20pro?= =?UTF-8?q?perty=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Student 인스턴스에 등록된 과목이 없으면 false --- Git_ Exercise/Student.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Git_ Exercise/Student.swift b/Git_ Exercise/Student.swift index c187902..591a540 100644 --- a/Git_ Exercise/Student.swift +++ b/Git_ Exercise/Student.swift @@ -11,6 +11,10 @@ final class Student: Codable { let name: String private(set) var scores = [String:Score]() + var isCourseEmpty: Bool { + return scores.isEmpty + } + init(name: String) { self.name = name } From eef683c4a49eb7f5db1a9760d80144493d77e80a Mon Sep 17 00:00:00 2001 From: Sei Kim Date: Mon, 19 Dec 2022 11:28:25 +0900 Subject: [PATCH 14/34] =?UTF-8?q?feat:=20Student=20-=20averageScore=20prop?= =?UTF-8?q?erty=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Git_ Exercise/Student.swift | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Git_ Exercise/Student.swift b/Git_ Exercise/Student.swift index 591a540..7997050 100644 --- a/Git_ Exercise/Student.swift +++ b/Git_ Exercise/Student.swift @@ -15,6 +15,11 @@ final class Student: Codable { return scores.isEmpty } + var averageScore: Float { + let total = scores.values.reduce(0) { $0 + $1.rawValue } + return total/Float(scores.values.count) + } + init(name: String) { self.name = name } From b99677c0619718fc027fd07c31f2dd7d0939858b Mon Sep 17 00:00:00 2001 From: Sei Kim Date: Mon, 19 Dec 2022 11:28:50 +0900 Subject: [PATCH 15/34] =?UTF-8?q?feat:=20Student=20-=20allScoresDescriptio?= =?UTF-8?q?n=20property=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Git_ Exercise/Student.swift | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Git_ Exercise/Student.swift b/Git_ Exercise/Student.swift index 7997050..6cff3a7 100644 --- a/Git_ Exercise/Student.swift +++ b/Git_ Exercise/Student.swift @@ -20,6 +20,14 @@ final class Student: Codable { return total/Float(scores.values.count) } + var allScoresDescription: String { + var res = "" + for item in scores { + res += "\(item.key): \(item.value.description)\n" + } + return res + "평점: " + String(format: "%.2f", averageScore) + } + init(name: String) { self.name = name } From 5c672d7986f31328436f077e535ff3529181dd1d Mon Sep 17 00:00:00 2001 From: Sei Kim Date: Mon, 19 Dec 2022 11:29:09 +0900 Subject: [PATCH 16/34] =?UTF-8?q?feat:=20Student=20-=20update=20method=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit input인 course와 score로 인스턴스의 scores Dictionary 업데이트 --- Git_ Exercise/Student.swift | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Git_ Exercise/Student.swift b/Git_ Exercise/Student.swift index 6cff3a7..6509641 100644 --- a/Git_ Exercise/Student.swift +++ b/Git_ Exercise/Student.swift @@ -31,4 +31,9 @@ final class Student: Codable { init(name: String) { self.name = name } + + func update(course: String, score: Score) { + scores.updateValue(score, forKey: course) + } + } From c8c86c94650a1f6ca4d50d1ad6b5cc72a2945b8c Mon Sep 17 00:00:00 2001 From: Sei Kim Date: Mon, 19 Dec 2022 11:31:24 +0900 Subject: [PATCH 17/34] =?UTF-8?q?feat:=20Student=20-=20remove(course:)=20m?= =?UTF-8?q?ethod=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Git_ Exercise/Student.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Git_ Exercise/Student.swift b/Git_ Exercise/Student.swift index 6509641..6b3dbc8 100644 --- a/Git_ Exercise/Student.swift +++ b/Git_ Exercise/Student.swift @@ -36,4 +36,7 @@ final class Student: Codable { scores.updateValue(score, forKey: course) } + func remove(course: String) -> Score? { + return scores.removeValue(forKey: course) + } } From b0e45816f1a82bb0b66b1869ecef8ff8c55cd6e1 Mon Sep 17 00:00:00 2001 From: Sei Kim Date: Mon, 19 Dec 2022 11:31:50 +0900 Subject: [PATCH 18/34] =?UTF-8?q?feat:=20StudentList=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Git_ Exercise/Student.swift | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Git_ Exercise/Student.swift b/Git_ Exercise/Student.swift index 6b3dbc8..245d355 100644 --- a/Git_ Exercise/Student.swift +++ b/Git_ Exercise/Student.swift @@ -40,3 +40,9 @@ final class Student: Codable { return scores.removeValue(forKey: course) } } + +//MARK: - Student DataStructure + +struct StudentList: Codable { + let students: [Student] +} From e80397b61156797af8a82ac7f94d01ebdc151e57 Mon Sep 17 00:00:00 2001 From: Sei Kim Date: Mon, 19 Dec 2022 11:32:48 +0900 Subject: [PATCH 19/34] =?UTF-8?q?feat:=20Score=20structure=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Git_ Exercise.xcodeproj/project.pbxproj | 4 +++ Git_ Exercise/Score.swift | 45 +++++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 Git_ Exercise/Score.swift diff --git a/Git_ Exercise.xcodeproj/project.pbxproj b/Git_ Exercise.xcodeproj/project.pbxproj index ddb56a8..cb0047f 100644 --- a/Git_ Exercise.xcodeproj/project.pbxproj +++ b/Git_ Exercise.xcodeproj/project.pbxproj @@ -13,6 +13,7 @@ 40841A572950008400E540E4 /* Info.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40841A562950008400E540E4 /* Info.swift */; }; 40841A592950022400E540E4 /* Status.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40841A582950022400E540E4 /* Status.swift */; }; 40841A5B2950031B00E540E4 /* Student.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40841A5A2950031B00E540E4 /* Student.swift */; }; + 40841A5D295004B200E540E4 /* Score.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40841A5C295004B200E540E4 /* Score.swift */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -35,6 +36,7 @@ 40841A562950008400E540E4 /* Info.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Info.swift; sourceTree = ""; }; 40841A582950022400E540E4 /* Status.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Status.swift; sourceTree = ""; }; 40841A5A2950031B00E540E4 /* Student.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Student.swift; sourceTree = ""; }; + 40841A5C295004B200E540E4 /* Score.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Score.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -73,6 +75,7 @@ 40841A562950008400E540E4 /* Info.swift */, 40841A582950022400E540E4 /* Status.swift */, 40841A5A2950031B00E540E4 /* Student.swift */, + 40841A5C295004B200E540E4 /* Score.swift */, ); path = "Git_ Exercise"; sourceTree = ""; @@ -135,6 +138,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 40841A5D295004B200E540E4 /* Score.swift in Sources */, 40841A53294FFE1F00E540E4 /* Error.swift in Sources */, 40841A5B2950031B00E540E4 /* Student.swift in Sources */, 40841A592950022400E540E4 /* Status.swift in Sources */, diff --git a/Git_ Exercise/Score.swift b/Git_ Exercise/Score.swift new file mode 100644 index 0000000..8cf1f55 --- /dev/null +++ b/Git_ Exercise/Score.swift @@ -0,0 +1,45 @@ +// +// Score.swift +// Git_ Exercise +// +// Created by sei_dev on 12/19/22. +// + +import Foundation + +enum Score: Float, Codable { + case APlus = 4.5 + case A = 4 + case BPlus = 3.5 + case B = 3 + case CPlus = 2.5 + case C = 2 + case DPlus = 1.5 + case D = 1 + case F = 0 + + init?(score: String) { + switch score { + case "A+", "a+", "4.5": + self = .APlus + case "A", "a", "A0", "a0", "4", "4.0": + self = .A + case "B+", "b+", "3.5": + self = .BPlus + case "B", "b", "B0", "b0", "3", "3.0": + self = .B + case "C+", "c+", "2.5": + self = .CPlus + case "C", "c", "C0", "c0", "2", "2.0": + self = .C + case "D+", "d+", "1.5": + self = .DPlus + case "D", "d", "D0", "d0", "1", "1.0": + self = .D + case "F", "f", "0", "0.0": + self = .F + default: + return nil + } + } +} From 6ac2785a91430b78dc57c3d26cd7901a191d9b08 Mon Sep 17 00:00:00 2001 From: Sei Kim Date: Mon, 19 Dec 2022 11:33:11 +0900 Subject: [PATCH 20/34] =?UTF-8?q?feat:=20Score=20-=20description=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Git_ Exercise/Score.swift | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/Git_ Exercise/Score.swift b/Git_ Exercise/Score.swift index 8cf1f55..ba572c4 100644 --- a/Git_ Exercise/Score.swift +++ b/Git_ Exercise/Score.swift @@ -18,6 +18,29 @@ enum Score: Float, Codable { case D = 1 case F = 0 + var description: String { + switch self { + case .APlus: + return "A+" + case .A: + return "A0" + case .BPlus: + return "B+" + case .B: + return "B0" + case .CPlus: + return "C+" + case .C: + return "C0" + case .DPlus: + return "D+" + case .D: + return "D0" + case .F: + return "F" + } + } + init?(score: String) { switch score { case "A+", "a+", "4.5": From 424fa1e8495550c5e207c01c1392f5d1d5ab3b07 Mon Sep 17 00:00:00 2001 From: Sei Kim Date: Mon, 19 Dec 2022 11:35:25 +0900 Subject: [PATCH 21/34] =?UTF-8?q?feat:=20CreditManager=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Git_ Exercise.xcodeproj/project.pbxproj | 4 +++ Git_ Exercise/CreditManager.swift | 38 +++++++++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 Git_ Exercise/CreditManager.swift diff --git a/Git_ Exercise.xcodeproj/project.pbxproj b/Git_ Exercise.xcodeproj/project.pbxproj index cb0047f..e1afd23 100644 --- a/Git_ Exercise.xcodeproj/project.pbxproj +++ b/Git_ Exercise.xcodeproj/project.pbxproj @@ -14,6 +14,7 @@ 40841A592950022400E540E4 /* Status.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40841A582950022400E540E4 /* Status.swift */; }; 40841A5B2950031B00E540E4 /* Student.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40841A5A2950031B00E540E4 /* Student.swift */; }; 40841A5D295004B200E540E4 /* Score.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40841A5C295004B200E540E4 /* Score.swift */; }; + 40841A5F2950051200E540E4 /* CreditManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40841A5E2950051200E540E4 /* CreditManager.swift */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -37,6 +38,7 @@ 40841A582950022400E540E4 /* Status.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Status.swift; sourceTree = ""; }; 40841A5A2950031B00E540E4 /* Student.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Student.swift; sourceTree = ""; }; 40841A5C295004B200E540E4 /* Score.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Score.swift; sourceTree = ""; }; + 40841A5E2950051200E540E4 /* CreditManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreditManager.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -76,6 +78,7 @@ 40841A582950022400E540E4 /* Status.swift */, 40841A5A2950031B00E540E4 /* Student.swift */, 40841A5C295004B200E540E4 /* Score.swift */, + 40841A5E2950051200E540E4 /* CreditManager.swift */, ); path = "Git_ Exercise"; sourceTree = ""; @@ -142,6 +145,7 @@ 40841A53294FFE1F00E540E4 /* Error.swift in Sources */, 40841A5B2950031B00E540E4 /* Student.swift in Sources */, 40841A592950022400E540E4 /* Status.swift in Sources */, + 40841A5F2950051200E540E4 /* CreditManager.swift in Sources */, 40841A572950008400E540E4 /* Info.swift in Sources */, 40841A55294FFF5400E540E4 /* IOManager.swift in Sources */, 2768CA08294F453B00990B98 /* main.swift in Sources */, diff --git a/Git_ Exercise/CreditManager.swift b/Git_ Exercise/CreditManager.swift new file mode 100644 index 0000000..fd74bc9 --- /dev/null +++ b/Git_ Exercise/CreditManager.swift @@ -0,0 +1,38 @@ +// +// CreditManager.swift +// Git_ Exercise +// +// Created by sei_dev on 12/19/22. +// + +import Foundation + +/// creditManager의 DataFile 관련 정보들 +enum DataFile { + /// 데이터가 저장되고 로드하는 json 파일 이름 + static let name = "data.json" + /// 파일이 저장될 Directory + static let directory: String = FileManager.default.currentDirectoryPath + static let pathString = DataFile.directory.appending(DataFile.name) + static var pathUrl: URL { + if #available(macOS 13.0, *) { + return URL(filePath: DataFile.directory.appending(DataFile.name)) + } else { + return URL(fileURLWithPath: DataFile.directory.appending(DataFile.name)) + } + } +} + +final class CreditManager { + /// CreditManager - singleton + static let shared = CreditManager() + private init() { } + + /// CreditManager의 현재 status + private var status: Status = .start + /// CreditManager에 등록된 Student의 List + private var students = [Student]() + + func run() { + } +} From f63f0f76618a10d0c070939b787032cc2f7d24e4 Mon Sep 17 00:00:00 2001 From: Sei Kim Date: Mon, 19 Dec 2022 11:36:00 +0900 Subject: [PATCH 22/34] =?UTF-8?q?feat:=20parse=20method=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Git_ Exercise/CreditManager.swift | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Git_ Exercise/CreditManager.swift b/Git_ Exercise/CreditManager.swift index fd74bc9..db3a4fe 100644 --- a/Git_ Exercise/CreditManager.swift +++ b/Git_ Exercise/CreditManager.swift @@ -35,4 +35,12 @@ final class CreditManager { func run() { } + + /// status 별 input parse + private func parse(input: String) throws -> ParsedInput { + guard let parsedInput = status.parse(input: input) else { + throw status == .start ? CMError.invalidStartInput : IOError.wrongInput + } + return parsedInput + } } From b533e30d169a508a32546c51305e00d2f02f7f63 Mon Sep 17 00:00:00 2001 From: Sei Kim Date: Mon, 19 Dec 2022 11:45:44 +0900 Subject: [PATCH 23/34] =?UTF-8?q?feat:=20start=20method=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Git_ Exercise/CreditManager.swift | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Git_ Exercise/CreditManager.swift b/Git_ Exercise/CreditManager.swift index db3a4fe..800806e 100644 --- a/Git_ Exercise/CreditManager.swift +++ b/Git_ Exercise/CreditManager.swift @@ -44,3 +44,21 @@ final class CreditManager { return parsedInput } } + +//MARK: - Start + +extension CreditManager { + /// 입력에 따라 credit manager의 status 변경 + private func start(_ input: ParsedInput) throws { + guard let nextStatus = input[0] as? Status else { + throw CMError.invalidStartInput + } + guard nextStatus != .exit else { + throw CMError.quitProgram + } + guard [Status.start, Status.addStudent].contains(nextStatus) || false == students.isEmpty else { + throw CMError.emptyStudents + } + self.status = nextStatus + } +} From 0b6932262e6bf1403b2f5c3da26518b29259daf5 Mon Sep 17 00:00:00 2001 From: Sei Kim Date: Mon, 19 Dec 2022 13:04:35 +0900 Subject: [PATCH 24/34] =?UTF-8?q?feat:=20CreditManager=20-=20Add=20Student?= =?UTF-8?q?=20method=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Git_ Exercise/CreditManager.swift | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/Git_ Exercise/CreditManager.swift b/Git_ Exercise/CreditManager.swift index 800806e..e79df64 100644 --- a/Git_ Exercise/CreditManager.swift +++ b/Git_ Exercise/CreditManager.swift @@ -62,3 +62,27 @@ extension CreditManager { self.status = nextStatus } } + +//MARK: - AddStudent + +extension CreditManager { + /// 입력받은 학생을 students에 추가 + /// + /// Error occurs when + /// - 입력받은 학생이 이미 존재 + private func add(student input: ParsedInput) throws { + guard let name = input[0] as? String else { + throw IOError.wrongInput + } + guard false == exists(student: name) else { + throw CMError.studentAleadyExists(name: name) + } + let student = Student(name: name) + students.append(student) + } + + /// 학생이 등록되어 있다면 true + private func exists(student name: String) -> Bool { + return students.contains { $0.name == name } + } +} From f3026d90f673e4e4c70efdedb46d74681fb5ebfb Mon Sep 17 00:00:00 2001 From: Sei Kim Date: Mon, 19 Dec 2022 13:05:00 +0900 Subject: [PATCH 25/34] =?UTF-8?q?feat:=20CreditManager=20-=20Delete=20Stud?= =?UTF-8?q?ent=20method=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Git_ Exercise/CreditManager.swift | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Git_ Exercise/CreditManager.swift b/Git_ Exercise/CreditManager.swift index e79df64..eb4e857 100644 --- a/Git_ Exercise/CreditManager.swift +++ b/Git_ Exercise/CreditManager.swift @@ -86,3 +86,25 @@ extension CreditManager { return students.contains { $0.name == name } } } + +//MARK: - Delete Student + +extension CreditManager { + /// 입력받은 학생을 students에서 삭제 + /// + /// Error occurs when + /// - 등록된 학생이 0명 + /// - 입력받은 학생이 존재하지 않음 + private func delete(student input: ParsedInput) throws { + guard false == students.isEmpty else { + throw CMError.emptyStudents + } + guard let name = input[0] as? String else { + throw IOError.wrongInput + } + guard exists(student: name) else { + throw CMError.studentNotFound(name: name) + } + students.removeAll { $0.name == name } + } +} From c8082630bd1255072184d376451030778710a73c Mon Sep 17 00:00:00 2001 From: Sei Kim Date: Mon, 19 Dec 2022 13:05:32 +0900 Subject: [PATCH 26/34] =?UTF-8?q?feat:=20CreditManager=20-=20Add=20Score?= =?UTF-8?q?=20method=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Git_ Exercise/CreditManager.swift | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/Git_ Exercise/CreditManager.swift b/Git_ Exercise/CreditManager.swift index eb4e857..7a5de19 100644 --- a/Git_ Exercise/CreditManager.swift +++ b/Git_ Exercise/CreditManager.swift @@ -108,3 +108,24 @@ extension CreditManager { students.removeAll { $0.name == name } } } + + +//MARK: - Add Score + +extension CreditManager { + /// 등록된 학생에 course, score 정보 추가 + /// + /// Error occurs when + /// - 입력받은 학생이 존재하지 않음 + private func add(score input: ParsedInput) throws { + guard let name = input[0] as? String, + let course = input[1] as? String, + let score = input[2] as? Score else { + throw IOError.wrongInput + } + guard let student = students.first(where: { $0.name == name}) else { + throw CMError.studentNotFound(name: name) + } + student.update(course: course, score: score) + } +} From e9dc48ac4d497f24356ffb006e885aed5fd4e639 Mon Sep 17 00:00:00 2001 From: Sei Kim Date: Mon, 19 Dec 2022 13:05:57 +0900 Subject: [PATCH 27/34] =?UTF-8?q?feat:=20CreditManager=20-=20Delete=20Scor?= =?UTF-8?q?e=20method=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Git_ Exercise/CreditManager.swift | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Git_ Exercise/CreditManager.swift b/Git_ Exercise/CreditManager.swift index 7a5de19..7933415 100644 --- a/Git_ Exercise/CreditManager.swift +++ b/Git_ Exercise/CreditManager.swift @@ -129,3 +129,25 @@ extension CreditManager { student.update(course: course, score: score) } } + +//MARK: - Delete Score + +extension CreditManager { + /// 등록된 학생의 course 정보 삭제 + /// + /// Error occurs when + /// - 입력받은 학생이 존재하지 않음 + /// - 학생 정보에 해당 과목이 등록되어 있지 않음 + private func delete(score input: ParsedInput) throws { + guard let name = input[0] as? String, + let course = input[1] as? String else { + throw IOError.wrongInput + } + guard let student = students.first(where: { $0.name == name}) else { + throw CMError.studentNotFound(name: name) + } + guard student.remove(course: course) != nil else { + throw CMError.courseNotFound(name: name, course: course) + } + } +} From 4dc03bad6e564e9540f93912fdd35aec25851334 Mon Sep 17 00:00:00 2001 From: Sei Kim Date: Mon, 19 Dec 2022 13:06:35 +0900 Subject: [PATCH 28/34] =?UTF-8?q?feat:=20CreditManager=20-=20Show(score:)?= =?UTF-8?q?=20method=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Git_ Exercise/CreditManager.swift | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Git_ Exercise/CreditManager.swift b/Git_ Exercise/CreditManager.swift index 7933415..065a690 100644 --- a/Git_ Exercise/CreditManager.swift +++ b/Git_ Exercise/CreditManager.swift @@ -151,3 +151,25 @@ extension CreditManager { } } } + +//MARK: - Show Average Score + +extension CreditManager { + /// 등록된 학생의 전체 과목과 평점 확인 + /// + /// Error occurs when + /// - 입력받은 학생이 존재하지 않음 + /// - 학생 정보에 등록된 과목이 없음 + private func show(score input: ParsedInput) throws { + guard let name = input[0] as? String else { + throw IOError.wrongInput + } + guard let student = students.first(where: { $0.name == name}) else { + throw CMError.studentNotFound(name: name) + } + guard false == student.scores.isEmpty else { + throw CMError.emptyCourse(name: name) + } + IOManager.writeMessage(student.allScoresDescription) + } +} From 84f38ecc80c20ad9d9d2d1b84e15bcf799cec0bc Mon Sep 17 00:00:00 2001 From: Sei Kim Date: Mon, 19 Dec 2022 13:59:28 +0900 Subject: [PATCH 29/34] =?UTF-8?q?feat:=20CreditManager=20-=20saveData=20me?= =?UTF-8?q?thod=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Git_ Exercise/CreditManager.swift | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/Git_ Exercise/CreditManager.swift b/Git_ Exercise/CreditManager.swift index 065a690..04bc836 100644 --- a/Git_ Exercise/CreditManager.swift +++ b/Git_ Exercise/CreditManager.swift @@ -173,3 +173,26 @@ extension CreditManager { IOManager.writeMessage(student.allScoresDescription) } } + + +extension CreditManager { + /// students property를 json 파일에 저장 + private func saveData() { + let encoder = JSONEncoder() + encoder.outputFormatting = .prettyPrinted + do { + let data = try encoder.encode(StudentList(students: students)) + + if false == FileManager.default.fileExists(atPath: DataFile.pathString) { + FileManager.default.createFile(atPath: DataFile.pathString, contents: nil) + } + + try data.write(to: DataFile.pathUrl) + let names = students.map {$0.name} + + IOManager.writeMessage(Info.Data.saved(names: names), type: .reaction) + } catch { + IOManager.writeMessage(error.localizedDescription, type: .error) + } + } +} From 7f3c64614d503c7d2b54d35e57aa557c4349382d Mon Sep 17 00:00:00 2001 From: Sei Kim Date: Mon, 19 Dec 2022 14:00:16 +0900 Subject: [PATCH 30/34] =?UTF-8?q?feat:=20CreditManager=20-=20loadData=20me?= =?UTF-8?q?thod=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Git_ Exercise/CreditManager.swift | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Git_ Exercise/CreditManager.swift b/Git_ Exercise/CreditManager.swift index 04bc836..c320a9b 100644 --- a/Git_ Exercise/CreditManager.swift +++ b/Git_ Exercise/CreditManager.swift @@ -195,4 +195,17 @@ extension CreditManager { IOManager.writeMessage(error.localizedDescription, type: .error) } } + + /// json 파일 데이터를 students property에 불러오기 + private func loadData() { + guard let data = try? Data(contentsOf: DataFile.pathUrl), + let studentList = try? JSONDecoder().decode(StudentList.self, from: data) else { + IOManager.writeMessage(Info.Warning.failedToLoadData, type: .error) + return + } + students = studentList.students + + let names = students.map {$0.name} + IOManager.writeMessage(Info.Data.loaded(names: names), type: .reaction) + } } From 0bf362f49829fe4ee3f3017d578c542fc50b8d2a Mon Sep 17 00:00:00 2001 From: Sei Kim Date: Mon, 19 Dec 2022 14:01:14 +0900 Subject: [PATCH 31/34] =?UTF-8?q?feat:=20CreditManager=20-=20doWith=20meth?= =?UTF-8?q?od=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 입력과 상태에 따라 credit manager 작동 분기 - result infomation이 있다면 출력 - 실행 후 credit manager의 satus는 start로 변경 --- Git_ Exercise/CreditManager.swift | 33 +++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/Git_ Exercise/CreditManager.swift b/Git_ Exercise/CreditManager.swift index c320a9b..5e3528c 100644 --- a/Git_ Exercise/CreditManager.swift +++ b/Git_ Exercise/CreditManager.swift @@ -43,6 +43,39 @@ final class CreditManager { } return parsedInput } + + + /// 입력과 상태에 따라 CreditManager 작동 분기 + /// + /// - result Infomation이 있다면 출력한다 + /// - 실행 후 credit manager의 status는 start로 변경 + private func doWith(_ input: ParsedInput) throws { + do { + switch self.status { + case .start: + try start(input) + return + case .addStudent: + try add(student: input) + case .deleteStudent: + try delete(student: input) + case .addScore: + try add(score: input) + case .deleteScore: + try delete(score: input) + case .showScoreAverage: + try show(score: input) + case .exit: + return + } + } catch { + throw error + } + if let resInfo = status.resMessage(input: input) { + IOManager.writeMessage(resInfo, type: .reaction) + } + status = .start + } } //MARK: - Start From aa8d4019297d68cf4ae02904cbaeecba7fe48da6 Mon Sep 17 00:00:00 2001 From: Sei Kim Date: Mon, 19 Dec 2022 14:05:33 +0900 Subject: [PATCH 32/34] =?UTF-8?q?feat:=20CreditManager=20-=20run=20method?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Git_ Exercise/CreditManager.swift | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/Git_ Exercise/CreditManager.swift b/Git_ Exercise/CreditManager.swift index 5e3528c..3d9caa3 100644 --- a/Git_ Exercise/CreditManager.swift +++ b/Git_ Exercise/CreditManager.swift @@ -33,7 +33,30 @@ final class CreditManager { /// CreditManager에 등록된 Student의 List private var students = [Student]() + /// 1. 저장된 데이터 로드 + /// 2. 프로그램 상태에 맞는 info 메세지 출력 + /// 3. input 처리 및 실행 + /// 4. error발생 시 설명 출력 + /// - 종료 error 시 데이터 저장 및 프로그램 종료 func run() { + loadData() + while true { + do { + IOManager.writeMessage(status.infoMessage) + let input = try IOManager.getInput(isStartStatus: status == .start) + let parsedInput = try parse(input: input) + try doWith(parsedInput) + } catch { + IOManager.writeMessage(error.localizedDescription, type: .error) + switch error { + case CMError.quitProgram: + saveData() + return + default: + status = .start + } + } + } } /// status 별 input parse From 9bf6ac0f60739977f4ca87fd0a1af824e8f5d668 Mon Sep 17 00:00:00 2001 From: Sei Kim Date: Mon, 19 Dec 2022 14:06:14 +0900 Subject: [PATCH 33/34] =?UTF-8?q?feat:=20main=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Git_ Exercise/main.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Git_ Exercise/main.swift b/Git_ Exercise/main.swift index 986559b..8f83192 100644 --- a/Git_ Exercise/main.swift +++ b/Git_ Exercise/main.swift @@ -7,5 +7,5 @@ import Foundation -print("Hello, World!") - +let cm = CreditManager.shared +cm.run() From 6761330a6a2a3218722ce18e8029d1b4cc86824b Mon Sep 17 00:00:00 2001 From: Sei Kim Date: Mon, 19 Dec 2022 14:07:48 +0900 Subject: [PATCH 34/34] =?UTF-8?q?chore:=20main=20=EC=9E=91=EC=84=B1?= =?UTF-8?q?=EC=9E=90=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Git_ Exercise/main.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Git_ Exercise/main.swift b/Git_ Exercise/main.swift index 8f83192..11d507d 100644 --- a/Git_ Exercise/main.swift +++ b/Git_ Exercise/main.swift @@ -2,7 +2,7 @@ // main.swift // Git_ Exercise // -// Created by 잼킹 on 2022/12/18. +// Created by sei_dev on 2022/12/18. // import Foundation