From c2de11d721fdd6f5db4d74654c9052b9ad8dfd75 Mon Sep 17 00:00:00 2001 From: CODEMASTERJO Date: Tue, 20 Dec 2022 10:29:50 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=ED=95=99=EC=83=9D=EC=84=B1=EC=A0=81?= =?UTF-8?q?=EA=B4=80=EB=A6=AC=EC=8B=9C=EC=8A=A4=ED=85=9C=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 --- StudentGradeManager/.gitignore | 95 ++++++ .../project.pbxproj | 309 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../UserInterfaceState.xcuserstate | Bin 0 -> 27260 bytes .../xcschemes/xcschememanagement.plist | 14 + .../StudentGradeManager/Grade.swift | 68 ++++ .../StudentGradeManager/GradeManager.swift | 24 ++ .../GradeManagerSystem.swift | 134 ++++++++ .../StudentGradeManager/InputError.swift | 14 + .../StudentGradeManager/InputManager.swift | 121 +++++++ .../StudentGradeManager/Student.swift | 51 +++ .../StudentGradeManager/main.swift | 13 + 13 files changed, 858 insertions(+) create mode 100644 StudentGradeManager/.gitignore create mode 100644 StudentGradeManager/StudentGradeManager.xcodeproj/project.pbxproj create mode 100644 StudentGradeManager/StudentGradeManager.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 StudentGradeManager/StudentGradeManager.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 StudentGradeManager/StudentGradeManager.xcodeproj/project.xcworkspace/xcuserdata/jojo.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 StudentGradeManager/StudentGradeManager.xcodeproj/xcuserdata/jojo.xcuserdatad/xcschemes/xcschememanagement.plist create mode 100644 StudentGradeManager/StudentGradeManager/Grade.swift create mode 100644 StudentGradeManager/StudentGradeManager/GradeManager.swift create mode 100644 StudentGradeManager/StudentGradeManager/GradeManagerSystem.swift create mode 100644 StudentGradeManager/StudentGradeManager/InputError.swift create mode 100644 StudentGradeManager/StudentGradeManager/InputManager.swift create mode 100644 StudentGradeManager/StudentGradeManager/Student.swift create mode 100644 StudentGradeManager/StudentGradeManager/main.swift diff --git a/StudentGradeManager/.gitignore b/StudentGradeManager/.gitignore new file mode 100644 index 0000000..8ff29cc --- /dev/null +++ b/StudentGradeManager/.gitignore @@ -0,0 +1,95 @@ +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## DS_Store +.DS_Store + +## User settings +xcuserdata/ +xcuserdata/* +*.xcuserstate + +## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) +*.xcscmblueprint +*.xccheckout + +## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) +build/ +DerivedData/ +*.moved-aside +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 + +## Obj-C/Swift specific +*.hmap + +## App packaging +*.ipa +*.dSYM.zip +*.dSYM + +## Playgrounds +timeline.xctimeline +playground.xcworkspace + +# Swift Package Manager +# +# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. +# Packages/ +# Package.pins +# Package.resolved +# *.xcodeproj +# +# Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata +# hence it is not needed unless you have added a package configuration file to your project +# .swiftpm + +.build/ + +# CocoaPods +# +# We recommend against adding the Pods directory to your .gitignore. However +# you should judge for yourself, the pros and cons are mentioned at: +# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control +# +# Pods/ +# +# Add this line if you want to avoid checking in source code from the Xcode workspace +# *.xcworkspace + +# Carthage +# +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts + +Carthage/Build/ + +# Accio dependency management +Dependencies/ +.accio/ + +# fastlane +# +# It is recommended to not store the screenshots in the git repo. +# Instead, use fastlane to re-generate the screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://docs.fastlane.tools/best-practices/source-control/#source-control + +fastlane/report.xml +fastlane/Preview.html +fastlane/screenshots/**/*.png +fastlane/test_output + +# Code Injection +# +# After new code Injection tools there's a generated folder /iOSInjectionProject +# https://github.com/johnno1962/injectionforxcode + +iOSInjectionProject/ diff --git a/StudentGradeManager/StudentGradeManager.xcodeproj/project.pbxproj b/StudentGradeManager/StudentGradeManager.xcodeproj/project.pbxproj new file mode 100644 index 0000000..69fa8f5 --- /dev/null +++ b/StudentGradeManager/StudentGradeManager.xcodeproj/project.pbxproj @@ -0,0 +1,309 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 56; + objects = { + +/* Begin PBXBuildFile section */ + EBECF44E2951467F00F52364 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBECF44D2951467F00F52364 /* main.swift */; }; + EBECF455295146A400F52364 /* Student.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBECF454295146A400F52364 /* Student.swift */; }; + EBECF457295146E800F52364 /* Grade.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBECF456295146E800F52364 /* Grade.swift */; }; + EBECF459295146FD00F52364 /* GradeManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBECF458295146FD00F52364 /* GradeManager.swift */; }; + EBECF45B2951471200F52364 /* GradeManagerSystem.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBECF45A2951471200F52364 /* GradeManagerSystem.swift */; }; + EBECF45D2951473B00F52364 /* InputManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBECF45C2951473B00F52364 /* InputManager.swift */; }; + EBECF45F2951475100F52364 /* InputError.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBECF45E2951475100F52364 /* InputError.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + EBECF4482951467F00F52364 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + EBECF44A2951467F00F52364 /* StudentGradeManager */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = StudentGradeManager; sourceTree = BUILT_PRODUCTS_DIR; }; + EBECF44D2951467F00F52364 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; + EBECF454295146A400F52364 /* Student.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Student.swift; sourceTree = ""; }; + EBECF456295146E800F52364 /* Grade.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Grade.swift; sourceTree = ""; }; + EBECF458295146FD00F52364 /* GradeManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GradeManager.swift; sourceTree = ""; }; + EBECF45A2951471200F52364 /* GradeManagerSystem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GradeManagerSystem.swift; sourceTree = ""; }; + EBECF45C2951473B00F52364 /* InputManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InputManager.swift; sourceTree = ""; }; + EBECF45E2951475100F52364 /* InputError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InputError.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + EBECF4472951467F00F52364 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + EBECF4412951467F00F52364 = { + isa = PBXGroup; + children = ( + EBECF44C2951467F00F52364 /* StudentGradeManager */, + EBECF44B2951467F00F52364 /* Products */, + ); + sourceTree = ""; + }; + EBECF44B2951467F00F52364 /* Products */ = { + isa = PBXGroup; + children = ( + EBECF44A2951467F00F52364 /* StudentGradeManager */, + ); + name = Products; + sourceTree = ""; + }; + EBECF44C2951467F00F52364 /* StudentGradeManager */ = { + isa = PBXGroup; + children = ( + EBECF44D2951467F00F52364 /* main.swift */, + EBECF454295146A400F52364 /* Student.swift */, + EBECF456295146E800F52364 /* Grade.swift */, + EBECF458295146FD00F52364 /* GradeManager.swift */, + EBECF45A2951471200F52364 /* GradeManagerSystem.swift */, + EBECF45C2951473B00F52364 /* InputManager.swift */, + EBECF45E2951475100F52364 /* InputError.swift */, + ); + path = StudentGradeManager; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + EBECF4492951467F00F52364 /* StudentGradeManager */ = { + isa = PBXNativeTarget; + buildConfigurationList = EBECF4512951467F00F52364 /* Build configuration list for PBXNativeTarget "StudentGradeManager" */; + buildPhases = ( + EBECF4462951467F00F52364 /* Sources */, + EBECF4472951467F00F52364 /* Frameworks */, + EBECF4482951467F00F52364 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = StudentGradeManager; + productName = StudentGradeManager; + productReference = EBECF44A2951467F00F52364 /* StudentGradeManager */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + EBECF4422951467F00F52364 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1420; + LastUpgradeCheck = 1420; + TargetAttributes = { + EBECF4492951467F00F52364 = { + CreatedOnToolsVersion = 14.2; + }; + }; + }; + buildConfigurationList = EBECF4452951467F00F52364 /* Build configuration list for PBXProject "StudentGradeManager" */; + compatibilityVersion = "Xcode 14.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = EBECF4412951467F00F52364; + productRefGroup = EBECF44B2951467F00F52364 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + EBECF4492951467F00F52364 /* StudentGradeManager */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + EBECF4462951467F00F52364 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + EBECF45D2951473B00F52364 /* InputManager.swift in Sources */, + EBECF45F2951475100F52364 /* InputError.swift in Sources */, + EBECF44E2951467F00F52364 /* main.swift in Sources */, + EBECF455295146A400F52364 /* Student.swift in Sources */, + EBECF457295146E800F52364 /* Grade.swift in Sources */, + EBECF459295146FD00F52364 /* GradeManager.swift in Sources */, + EBECF45B2951471200F52364 /* GradeManagerSystem.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + EBECF44F2951467F00F52364 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 13.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + EBECF4502951467F00F52364 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 13.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Release; + }; + EBECF4522951467F00F52364 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + EBECF4532951467F00F52364 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + EBECF4452951467F00F52364 /* Build configuration list for PBXProject "StudentGradeManager" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + EBECF44F2951467F00F52364 /* Debug */, + EBECF4502951467F00F52364 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + EBECF4512951467F00F52364 /* Build configuration list for PBXNativeTarget "StudentGradeManager" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + EBECF4522951467F00F52364 /* Debug */, + EBECF4532951467F00F52364 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = EBECF4422951467F00F52364 /* Project object */; +} diff --git a/StudentGradeManager/StudentGradeManager.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/StudentGradeManager/StudentGradeManager.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/StudentGradeManager/StudentGradeManager.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/StudentGradeManager/StudentGradeManager.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/StudentGradeManager/StudentGradeManager.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/StudentGradeManager/StudentGradeManager.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/StudentGradeManager/StudentGradeManager.xcodeproj/project.xcworkspace/xcuserdata/jojo.xcuserdatad/UserInterfaceState.xcuserstate b/StudentGradeManager/StudentGradeManager.xcodeproj/project.xcworkspace/xcuserdata/jojo.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..3f8b9a5bd433e2f2cc9836f86e5913d17a47fe89 GIT binary patch literal 27260 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 H(enQQ3ZL8W literal 0 HcmV?d00001 diff --git a/StudentGradeManager/StudentGradeManager.xcodeproj/xcuserdata/jojo.xcuserdatad/xcschemes/xcschememanagement.plist b/StudentGradeManager/StudentGradeManager.xcodeproj/xcuserdata/jojo.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..80662c2 --- /dev/null +++ b/StudentGradeManager/StudentGradeManager.xcodeproj/xcuserdata/jojo.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + StudentGradeManager.xcscheme_^#shared#^_ + + orderHint + 0 + + + + diff --git a/StudentGradeManager/StudentGradeManager/Grade.swift b/StudentGradeManager/StudentGradeManager/Grade.swift new file mode 100644 index 0000000..c957283 --- /dev/null +++ b/StudentGradeManager/StudentGradeManager/Grade.swift @@ -0,0 +1,68 @@ +// +// Grade.swift +// StudentGradeManager +// +// Created by 조용현 on 2022/12/20. +// + +import Foundation + +enum Grade: Double { + case APlus = 4.5 + case AZero = 4.0 + case BPlus = 3.5 + case BZero = 3.0 + case CPlus = 2.5 + case CZero = 2.0 + case DPlus = 1.5 + case DZero = 1.0 + case F = 0.0 + + static func gradeForString(for gradeString: String) throws -> Grade { + switch gradeString { + case "A+": + return Grade.APlus + case "A0": + return Grade.AZero + case "B+": + return Grade.BPlus + case "B0": + return Grade.BZero + case "C+": + return Grade.CPlus + case "C0": + return Grade.CZero + case "D+": + return Grade.DPlus + case "D0": + return Grade.DZero + case "F": + return Grade.F + default: + throw InputError.invalidInput + } + } + + static func printGradeString(for grade: Grade) { + switch grade { + case .APlus: + print("A+") + case .AZero: + print("A0") + case .BPlus: + print("B+") + case .BZero: + print("B0") + case .CPlus: + print("C+") + case .CZero: + print("C0") + case .DPlus: + print("D+") + case .DZero: + print("D0") + case .F: + print("F") + } + } +} diff --git a/StudentGradeManager/StudentGradeManager/GradeManager.swift b/StudentGradeManager/StudentGradeManager/GradeManager.swift new file mode 100644 index 0000000..6ed744c --- /dev/null +++ b/StudentGradeManager/StudentGradeManager/GradeManager.swift @@ -0,0 +1,24 @@ +// +// GradeManager.swift +// StudentGradeManager +// +// Created by 조용현 on 2022/12/20. +// + +import Foundation + +class GradeManager { + + private let gradeManageSystem = GradeManagerSystem() + + func run() { + while !gradeManageSystem.isDone { + do { + let menuInput = try gradeManageSystem.receiveMenuInput() + gradeManageSystem.performMenuAction(menuInput: menuInput) + } catch { + print(error) + } + } + } +} diff --git a/StudentGradeManager/StudentGradeManager/GradeManagerSystem.swift b/StudentGradeManager/StudentGradeManager/GradeManagerSystem.swift new file mode 100644 index 0000000..4fc9867 --- /dev/null +++ b/StudentGradeManager/StudentGradeManager/GradeManagerSystem.swift @@ -0,0 +1,134 @@ +// +// GradeManagerSystem.swift +// StudentGradeManager +// +// Created by 조용현 on 2022/12/20. +// + +import Foundation + +class GradeManagerSystem { + + let inputManager = InputManager() + + var isDone = false + + enum Menu: String { + case addStudent = "1" + case removeStudent = "2" + case addOrModifyGrade = "3" + case removeGrade = "4" + case lookupGrade = "5" + case stopProgram = "X" + } + + let userDefaults = UserDefaults.standard + + var studentDictionary: [String: Student] = [:] + + func receiveMenuInput() throws -> String { + try inputManager.menuInput() + } + + func performMenuAction(menuInput: String) { + do { + switch Menu(rawValue: menuInput) { + case .addStudent: + let studentName = try inputManager.addStudentInput() + addStudent(studentName) + + case .removeStudent: + let studentName = try inputManager.removeStudentInput() + removeStudent(studentName) + + case .addOrModifyGrade: + let (studentName, subject, grade) = try inputManager.addOrModifyGradeInput() + addOrModifyGrade(for: studentName, withSubject: subject, as: grade) + + case .removeGrade: + let (studentName, subject) = try inputManager.removeGradeInput() + removeGrade(for: studentName, withSubject: subject) + + case .lookupGrade: + let studentName = try inputManager.findAverageInput() + lookupGrade(for: studentName) + + case .stopProgram: + stopProgram() + + case .none: + inputManager.printInvalidMenuInput() + } + } catch { + inputManager.printInvalidInput() + } + } + + func addStudent(_ studentName: String) { + guard studentDictionary[studentName] == nil else { + print("\(studentName)은 이미 존재하는 학생입니다. 추가하지 않습니다.") + return + } + + let newStudentEntity = Student(name: studentName) + studentDictionary[studentName] = newStudentEntity + print("\(studentName) 학생을 추가했습니다.") + } + + func removeStudent(_ studentName: String) { + guard studentDictionary[studentName] != nil else { + print("\(studentName) 학생을 찾지 못했습니다.") + return + } + + studentDictionary.removeValue(forKey: studentName) + print("\(studentName) 학생을 삭제하였습니다.") + } + + func addOrModifyGrade(for studentName: String, withSubject subject: String, as grade: String ) { + guard var student = studentDictionary[studentName] else { + print("\(studentName) 학생을 찾지 못했습니다.") + return + } + + student.updateGrade(for: subject, as: grade) + studentDictionary[studentName] = student + + print("\(studentName) 학생의 \(subject) 과목이 \(grade)로 추가(변경)되었습니다.") + } + + func removeGrade(for studentName: String, withSubject subject: String) { + guard var student = studentDictionary[studentName] else { + print("\(studentName) 학생을 찾지 못했습니다.") + return + } + + student.deleteGrade(for: subject) + studentDictionary[studentName] = student + + print("\(studentName) 학생의 \(subject) 과목의 성적이 삭제되었습니다.") + } + + func lookupGrade(for studentName: String) { + + guard let student = studentDictionary[studentName] else { + print("\(studentName) 학생을 찾지 못했습니다.") + return + } + + student.printAllGrades() + do { + let averageScore = try student.calculateAverageScore() + print("평점 : \(averageScore)") + } catch { + print("\(studentName) 학생은 입력된 성적이 없습니다.") + } + + } + + func stopProgram() { + isDone = true + inputManager.printCloseProgram() + } +} + diff --git a/StudentGradeManager/StudentGradeManager/InputError.swift b/StudentGradeManager/StudentGradeManager/InputError.swift new file mode 100644 index 0000000..24a7a4b --- /dev/null +++ b/StudentGradeManager/StudentGradeManager/InputError.swift @@ -0,0 +1,14 @@ +// +// InputError.swift +// StudentGradeManager +// +// Created by 조용현 on 2022/12/20. +// + +import Foundation + +enum InputError: Error { + case invalidMenuInput + case invalidInput + case emptyGrades +} diff --git a/StudentGradeManager/StudentGradeManager/InputManager.swift b/StudentGradeManager/StudentGradeManager/InputManager.swift new file mode 100644 index 0000000..6c2f91c --- /dev/null +++ b/StudentGradeManager/StudentGradeManager/InputManager.swift @@ -0,0 +1,121 @@ +// +// InputManager.swift +// StudentGradeManager +// +// Created by 조용현 on 2022/12/20. +// + +import Foundation + +struct InputManager { + + private let menuInputMessage = "원하는 기능을 입력해주세요\n1: 학생추가, 2: 학생삭제, 3: 성적추가(변경), 4: 성적삭제, 5: 평점보기, X: 종료" + private let invalidMenuInputMessage = "뭔가 입력이 잘못되었습니다. 1~5 사이의 숫자 혹은 X를 입력해주세요." + private let addStudentMessage = "추가할 학생의 이름을 입력해주세요" + private let removeStudentMessage = "삭제할 학생의 이름을 입력해주세요" + private let addGradeMessage = "성적을 추가할 학생의 이름, 과목 이름, 성적(A+, A0, F 등)을 띄어쓰기로 구분하여 차례로 작성해주세요.\n입력예) Mickey Swift A+\n만약에 학생의 성적 중 해당 과목이 존재하면 기존 점수가 갱신됩니다." + private let removeGradeMessage = "성적을 삭제할 학생의 이름, 과목 이름을 띄어쓰기로 구분하여 차례로 작성해주세요.\n입력예) Mickey Swift" + private let findAverageMessage = "평점을 알고싶은 학생의 이름을 입력해주세요." + private let invalidInputMessage = "입력이 잘못되었습니다. 다시 확인해주세요." + private let closeProgramMessage = "프로그램을 종료합니다..." + + func menuInput() throws -> String { + print(menuInputMessage) + + let receivedInput = readLine() + guard let receivedInput = receivedInput else { + throw InputError.invalidMenuInput + } + + return receivedInput + } + + func addStudentInput() throws -> String { + print(addStudentMessage) + let receivedInput = readLine() + + let regexExpression = "^[a-zA-Z0-9]*$" + let regexTest = NSPredicate(format:"SELF MATCHES %@", regexExpression) + + guard let receivedInput = receivedInput, receivedInput != "", regexTest.evaluate(with: receivedInput) else { + throw InputError.invalidInput + } + + return receivedInput + } + + func removeStudentInput() throws -> String { + print(removeStudentMessage) + + let receivedInput = readLine() + + let regexExpression = "^[a-zA-Z0-9]*$" + let regexTest = NSPredicate(format:"SELF MATCHES %@", regexExpression) + + guard let receivedInput = receivedInput, receivedInput != "", regexTest.evaluate(with: receivedInput) else { + throw InputError.invalidInput + } + + return receivedInput + } + + func addOrModifyGradeInput() throws -> (String, String, String) { + print(addGradeMessage) + + let receivedInput = readLine() + + let regexExpression = "[a-zA-Z0-9]+\\s[a-zA-Z0-9]+\\s([A, B, C, D]+[0, +]|[F])" + let regexTest = NSPredicate(format:"SELF MATCHES %@", regexExpression) + + guard let receivedInput = receivedInput, receivedInput != "", regexTest.evaluate(with: receivedInput) else { + throw InputError.invalidInput + } + + let inputComponents = receivedInput.split(separator: " ").map{ String($0) } + + return (inputComponents[0], inputComponents[1], inputComponents[2]) + } + + func removeGradeInput() throws -> (String, String) { + print(removeGradeMessage) + + let receivedInput = readLine() + + let regexExpression = "[a-zA-Z0-9]+\\s[a-zA-Z0-9]*$" + let regexTest = NSPredicate(format:"SELF MATCHES %@", regexExpression) + + guard let receivedInput = receivedInput, receivedInput != "", regexTest.evaluate(with: receivedInput) else { + throw InputError.invalidInput + } + + let inputComponents = receivedInput.split(separator: " ").map{ String($0) } + + return (inputComponents[0], inputComponents[1]) + } + + func findAverageInput() throws -> String { + print(findAverageMessage) + let receivedInput = readLine() + + let regexExpression = "^[a-zA-Z0-9]*$" + let regexTest = NSPredicate(format:"SELF MATCHES %@", regexExpression) + + guard let receivedInput = receivedInput, receivedInput != "", regexTest.evaluate(with: receivedInput) else { + throw InputError.invalidInput + } + + return receivedInput + } + + func printInvalidMenuInput() { + print(invalidMenuInputMessage) + } + + func printInvalidInput() { + print(invalidInputMessage) + } + + func printCloseProgram() { + print(closeProgramMessage) + } +} diff --git a/StudentGradeManager/StudentGradeManager/Student.swift b/StudentGradeManager/StudentGradeManager/Student.swift new file mode 100644 index 0000000..7942eee --- /dev/null +++ b/StudentGradeManager/StudentGradeManager/Student.swift @@ -0,0 +1,51 @@ +// +// Student.swift +// StudentGradeManager +// +// Created by 조용현 on 2022/12/20. +// + +import Foundation + +struct Student { + + var name: String + var gradeForSubject: [String: Grade] + + init(name: String) { + self.name = "" + self.gradeForSubject = [:] + } + + mutating func updateGrade(for subjuct: String, as grade: String) { + + do { + gradeForSubject[subjuct] = try Grade.gradeForString(for: grade) + } catch { + print(InputError.invalidInput) + } + } + + mutating func deleteGrade(for subject: String) { + gradeForSubject[subject] = nil + } + + func printAllGrades() { + for grade in gradeForSubject { + print(grade.key, terminator: ": ") + Grade.printGradeString(for: grade.value) + } + } + + func calculateAverageScore() throws -> Double { + guard gradeForSubject.count != 0 else { + throw InputError.emptyGrades + } + + let averageGrade = gradeForSubject.values + .map{ $0.rawValue } + .reduce(0.0, +) / Double(gradeForSubject.count) + + return averageGrade + } +} diff --git a/StudentGradeManager/StudentGradeManager/main.swift b/StudentGradeManager/StudentGradeManager/main.swift new file mode 100644 index 0000000..497081b --- /dev/null +++ b/StudentGradeManager/StudentGradeManager/main.swift @@ -0,0 +1,13 @@ +// +// main.swift +// StudentGradeManager +// +// Created by 조용현 on 2022/12/20. +// + +import Foundation + +let gradeManager = GradeManager() +gradeManager.run() + +