diff --git a/BankManagerConsoleApp/BankManagerConsoleApp.xcodeproj/project.pbxproj b/BankManagerConsoleApp/BankManagerConsoleApp.xcodeproj/project.pbxproj index 6b40a668..7f7d021e 100644 --- a/BankManagerConsoleApp/BankManagerConsoleApp.xcodeproj/project.pbxproj +++ b/BankManagerConsoleApp/BankManagerConsoleApp.xcodeproj/project.pbxproj @@ -7,8 +7,16 @@ objects = { /* Begin PBXBuildFile section */ + 1D9C82D72B6A2B1C0047245E /* Node.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D9C82D62B6A2B1C0047245E /* Node.swift */; }; + 1D9C82D92B6A2B270047245E /* LinkedList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D9C82D82B6A2B270047245E /* LinkedList.swift */; }; + 1D9C82DB2B6A2B2F0047245E /* Queue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D9C82DA2B6A2B2F0047245E /* Queue.swift */; }; + 847943632B6A2D3E00F85F0C /* Bank.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847943622B6A2D3E00F85F0C /* Bank.swift */; }; + 847943652B6A2D4800F85F0C /* Banker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847943642B6A2D4800F85F0C /* Banker.swift */; }; + 847943672B6A2D5300F85F0C /* Customer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847943662B6A2D5300F85F0C /* Customer.swift */; }; + 847943692B6A342200F85F0C /* Double+.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847943682B6A342200F85F0C /* Double+.swift */; }; + 849EDAD02B6BB1BA00096E84 /* Messages.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849EDACF2B6BB1BA00096E84 /* Messages.swift */; }; + 849EDAD22B6BBB2500096E84 /* TaskType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849EDAD12B6BBB2500096E84 /* TaskType.swift */; }; C7694E7A259C3EC00053667F /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7694E79259C3EC00053667F /* main.swift */; }; - C7D65D1B259C8190005510E0 /* BankManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7D65D1A259C8190005510E0 /* BankManager.swift */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -24,9 +32,17 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 1D9C82D62B6A2B1C0047245E /* Node.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Node.swift; sourceTree = ""; }; + 1D9C82D82B6A2B270047245E /* LinkedList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkedList.swift; sourceTree = ""; }; + 1D9C82DA2B6A2B2F0047245E /* Queue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Queue.swift; sourceTree = ""; }; + 847943622B6A2D3E00F85F0C /* Bank.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Bank.swift; sourceTree = ""; }; + 847943642B6A2D4800F85F0C /* Banker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Banker.swift; sourceTree = ""; }; + 847943662B6A2D5300F85F0C /* Customer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Customer.swift; sourceTree = ""; }; + 847943682B6A342200F85F0C /* Double+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Double+.swift"; sourceTree = ""; }; + 849EDACF2B6BB1BA00096E84 /* Messages.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Messages.swift; sourceTree = ""; }; + 849EDAD12B6BBB2500096E84 /* TaskType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaskType.swift; sourceTree = ""; }; C7694E76259C3EC00053667F /* BankManagerConsoleApp */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = BankManagerConsoleApp; sourceTree = BUILT_PRODUCTS_DIR; }; C7694E79259C3EC00053667F /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; - C7D65D1A259C8190005510E0 /* BankManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BankManager.swift; path = ../../BankManager.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -40,6 +56,27 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 1D9C82D42B6A2AD00047245E /* Queue */ = { + isa = PBXGroup; + children = ( + 1D9C82D62B6A2B1C0047245E /* Node.swift */, + 1D9C82D82B6A2B270047245E /* LinkedList.swift */, + 1D9C82DA2B6A2B2F0047245E /* Queue.swift */, + ); + path = Queue; + sourceTree = ""; + }; + 1D9C82D52B6A2AF00047245E /* Bank */ = { + isa = PBXGroup; + children = ( + 849EDAD12B6BBB2500096E84 /* TaskType.swift */, + 847943622B6A2D3E00F85F0C /* Bank.swift */, + 847943642B6A2D4800F85F0C /* Banker.swift */, + 847943662B6A2D5300F85F0C /* Customer.swift */, + ); + path = Bank; + sourceTree = ""; + }; C7694E6D259C3EC00053667F = { isa = PBXGroup; children = ( @@ -59,8 +96,11 @@ C7694E78259C3EC00053667F /* BankManagerConsoleApp */ = { isa = PBXGroup; children = ( - C7D65D1A259C8190005510E0 /* BankManager.swift */, + 849EDACF2B6BB1BA00096E84 /* Messages.swift */, + 847943682B6A342200F85F0C /* Double+.swift */, C7694E79259C3EC00053667F /* main.swift */, + 1D9C82D42B6A2AD00047245E /* Queue */, + 1D9C82D52B6A2AF00047245E /* Bank */, ); path = BankManagerConsoleApp; sourceTree = ""; @@ -122,8 +162,16 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 1D9C82D92B6A2B270047245E /* LinkedList.swift in Sources */, + 849EDAD02B6BB1BA00096E84 /* Messages.swift in Sources */, + 849EDAD22B6BBB2500096E84 /* TaskType.swift in Sources */, + 847943672B6A2D5300F85F0C /* Customer.swift in Sources */, + 847943692B6A342200F85F0C /* Double+.swift in Sources */, C7694E7A259C3EC00053667F /* main.swift in Sources */, - C7D65D1B259C8190005510E0 /* BankManager.swift in Sources */, + 847943652B6A2D4800F85F0C /* Banker.swift in Sources */, + 847943632B6A2D3E00F85F0C /* Bank.swift in Sources */, + 1D9C82D72B6A2B1C0047245E /* Node.swift in Sources */, + 1D9C82DB2B6A2B2F0047245E /* Queue.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/BankManagerConsoleApp/BankManagerConsoleApp/Bank/Bank.swift b/BankManagerConsoleApp/BankManagerConsoleApp/Bank/Bank.swift new file mode 100644 index 00000000..f704e5f4 --- /dev/null +++ b/BankManagerConsoleApp/BankManagerConsoleApp/Bank/Bank.swift @@ -0,0 +1,62 @@ +// +// Bank.swift +// BankManagerConsoleApp +// +// Created by dopamint on 1/31/24. +// + +import Foundation + +final class Bank { + + private var banker = Banker() + private var customerQueue = Queue() + private let depositSemaphore: DispatchSemaphore + private let loanSemaphore: DispatchSemaphore + private let group = DispatchGroup() + + init(depositBankerCount: Int, loanBankerCount: Int) { + self.depositSemaphore = DispatchSemaphore(value: depositBankerCount) + self.loanSemaphore = DispatchSemaphore(value: loanBankerCount) + } + + func open() { + let startTime = Date() + Messages.openBank.printMessage() + let numberOfCustomers = Int.random(in: 10...30) + + print("고객 수: \(numberOfCustomers)") + setUpCustomerQueue(count: numberOfCustomers) + + while let customer = customerQueue.dequeue() { + switch customer.taskType { + case .deposit: + serveCustomer(semaphore: depositSemaphore, customer: customer) + case .loan: + serveCustomer(semaphore: loanSemaphore, customer: customer) + } + } + group.wait() + let endTime = Date() + let elapsedTime = endTime.timeIntervalSince(startTime).formattedDecimal + Messages.closeBank(customerCount: numberOfCustomers, totalTime: elapsedTime).printMessage() + } + + private func serveCustomer(semaphore: DispatchSemaphore, customer: Customer) { + DispatchQueue.global().async(group: group) { + semaphore.wait() + self.banker.processCustomer(customer) + semaphore.signal() + } + } + + private func setUpCustomerQueue(count: Int) { + for number in 1...count { + let customer = Customer(number: number) + customerQueue.enqueue(customer) + } + } +} + + + diff --git a/BankManagerConsoleApp/BankManagerConsoleApp/Bank/Banker.swift b/BankManagerConsoleApp/BankManagerConsoleApp/Bank/Banker.swift new file mode 100644 index 00000000..72e7afcf --- /dev/null +++ b/BankManagerConsoleApp/BankManagerConsoleApp/Bank/Banker.swift @@ -0,0 +1,17 @@ +// +// Banker.swift +// BankManagerConsoleApp +// +// Created by dopamint on 1/31/24. +// + +import Foundation + +final class Banker { + + func processCustomer(_ customer: Customer) { + Messages.taskStart(number: customer.number, taskType: customer.taskType.description).printMessage() + Thread.sleep(forTimeInterval: customer.taskType.taskTime) + Messages.taskDone(number: customer.number, taskType: customer.taskType.description).printMessage() + } +} diff --git a/BankManagerConsoleApp/BankManagerConsoleApp/Bank/Customer.swift b/BankManagerConsoleApp/BankManagerConsoleApp/Bank/Customer.swift new file mode 100644 index 00000000..070f8330 --- /dev/null +++ b/BankManagerConsoleApp/BankManagerConsoleApp/Bank/Customer.swift @@ -0,0 +1,16 @@ +// +// Customer.swift +// BankManagerConsoleApp +// +// Created by dopamint on 1/31/24. +// +final class Customer { + let number: Int + let taskType: TaskType + + init(number: Int) { + self.number = number + self.taskType = TaskType.random() + } +} + diff --git a/BankManagerConsoleApp/BankManagerConsoleApp/Bank/TaskType.swift b/BankManagerConsoleApp/BankManagerConsoleApp/Bank/TaskType.swift new file mode 100644 index 00000000..b0ae593b --- /dev/null +++ b/BankManagerConsoleApp/BankManagerConsoleApp/Bank/TaskType.swift @@ -0,0 +1,34 @@ +// +// WorkType.swift +// BankManagerConsoleApp +// +// Created by dopamint on 2/1/24. +// +enum TaskType { + case loan + case deposit +} + +extension TaskType { + var description: String { + switch self { + case .loan: + return "대출" + case .deposit: + return "예금" + } + } + + var taskTime: Double { + switch self { + case .loan: + return 1.1 + case .deposit: + return 0.7 + } + } + + static func random() -> TaskType { + return Bool.random() ? .loan : .deposit + } +} diff --git a/BankManagerConsoleApp/BankManagerConsoleApp/Double+.swift b/BankManagerConsoleApp/BankManagerConsoleApp/Double+.swift new file mode 100644 index 00000000..b2a86574 --- /dev/null +++ b/BankManagerConsoleApp/BankManagerConsoleApp/Double+.swift @@ -0,0 +1,12 @@ +// +// String+.swift +// BankManagerConsoleApp +// +// Created by dopamint on 1/31/24. +// + +extension Double { + var formattedDecimal: String { + return String(format: "%.2f", self) + } +} diff --git a/BankManagerConsoleApp/BankManagerConsoleApp/Messages.swift b/BankManagerConsoleApp/BankManagerConsoleApp/Messages.swift new file mode 100644 index 00000000..4aa3c386 --- /dev/null +++ b/BankManagerConsoleApp/BankManagerConsoleApp/Messages.swift @@ -0,0 +1,41 @@ +// +// Messages.swift +// BankManagerConsoleApp +// +// Created by dopamint on 2/1/24. +// + +enum Messages { + case menu + case exit + case openBank + case taskStart(number: Int, taskType: String) + case taskDone(number: Int, taskType: String) + case closeBank(customerCount: Int, totalTime: String) + case menuError + case numberError +} + +extension Messages { + func printMessage() { + switch self { + case .menu: + print("1 : 은행계정\n2 : 종료") + print("입력 : ", terminator: "") + case .exit: + print("프로그램을 종료합니다.") + case .openBank: + print("은행 문이 열렸습니다.") + case .taskStart(let number, let taskType): + print("\(number) 고객 \(taskType)업무 시작") + case .taskDone(let number, let taskType): + print("\(number) 고객 \(taskType)업무 종료") + case .closeBank(let customerCount, let totalTime): + print("업무가 마감되었습니다. 오늘 업무를 처리한 고객은 총 \(customerCount)명 이며, 총 업무시간은 \(totalTime)초 입니다.") + case .menuError: + print("올바른 메뉴를 선택해주세요.") + case .numberError: + print("숫자를 입력해주세요.") + } + } +} diff --git a/BankManagerConsoleApp/BankManagerConsoleApp/Queue/LinkedList.swift b/BankManagerConsoleApp/BankManagerConsoleApp/Queue/LinkedList.swift new file mode 100644 index 00000000..a72bd778 --- /dev/null +++ b/BankManagerConsoleApp/BankManagerConsoleApp/Queue/LinkedList.swift @@ -0,0 +1,57 @@ +// +// LinkedList.swift +// BankManagerConsoleApp +// +// Created by yujaehong on 1/31/24. +// + +final class LinkedList { + var front: Node? + var rear: Node? + + init(front: Node? = nil, rear: Node? = nil) { + self.front = front + self.rear = rear + } + + var first: T? { + return front?.value + } + + var isEmpty: Bool { + return front == nil + } +} + +extension LinkedList { + func append(_ value: T) { + let newNode = Node(value) + + if isEmpty { + front = newNode + rear = front + } else { + rear?.next = newNode + rear = newNode + } + } + + func removeFirst() -> T? { + if front === rear { + let result = front + front = nil + rear = nil + return result?.value + } + guard let currentFront = front else { return nil } + front = front?.next + return currentFront.value + } + + func removeAll() { + front = nil + rear = nil + } +} + + diff --git a/BankManagerConsoleApp/BankManagerConsoleApp/Queue/Node.swift b/BankManagerConsoleApp/BankManagerConsoleApp/Queue/Node.swift new file mode 100644 index 00000000..3beb0840 --- /dev/null +++ b/BankManagerConsoleApp/BankManagerConsoleApp/Queue/Node.swift @@ -0,0 +1,15 @@ +// +// Node.swift +// BankManagerConsoleApp +// +// Created by yujaehong on 1/31/24. +// +final class Node { + var value: T + var next: Node? + + init(_ value: T, _ next: Node? = nil) { + self.value = value + self.next = next + } +} diff --git a/BankManagerConsoleApp/BankManagerConsoleApp/Queue/Queue.swift b/BankManagerConsoleApp/BankManagerConsoleApp/Queue/Queue.swift new file mode 100644 index 00000000..223ac562 --- /dev/null +++ b/BankManagerConsoleApp/BankManagerConsoleApp/Queue/Queue.swift @@ -0,0 +1,37 @@ +// +// Queue.swift +// BankManagerConsoleApp +// +// Created by yujaehong on 1/31/24. +// + +final class Queue { + private var linkedList: LinkedList + + init(linkedList: LinkedList = LinkedList()) { + self.linkedList = linkedList + } +} + +extension Queue { + func enqueue(_ value: T) { + linkedList.append(value) + } + + + func dequeue() -> T? { + return linkedList.removeFirst() + } + + func clear() { + linkedList.removeAll() + } + + func peek() -> T? { + return linkedList.first + } + + func isEmpty() -> Bool { + return linkedList.isEmpty + } +} diff --git a/BankManagerConsoleApp/BankManagerConsoleApp/main.swift b/BankManagerConsoleApp/BankManagerConsoleApp/main.swift index 1aa9854c..55c976d1 100644 --- a/BankManagerConsoleApp/BankManagerConsoleApp/main.swift +++ b/BankManagerConsoleApp/BankManagerConsoleApp/main.swift @@ -2,6 +2,28 @@ // BankManagerConsoleApp - main.swift // Created by yagom. // Copyright © yagom academy. All rights reserved. -// +// + +func operateBank() { + let bank = Bank(depositBankerCount: 2, loanBankerCount: 1) + + while true { + Messages.menu.printMessage() + if let choice = readLine(), + let menu = Int(choice) { + switch menu { + case 1: + bank.open() + case 2: + Messages.exit.printMessage() + return + default: + Messages.menuError.printMessage() + } + } else { + Messages.numberError.printMessage() + } + } +} -import Foundation +operateBank()