diff --git a/BankManagerConsoleApp/BankManagerConsoleApp/Bank/Bank.swift b/BankManagerConsoleApp/BankManagerConsoleApp/Bank/Bank.swift index 67ffcc65..5d17720e 100644 --- a/BankManagerConsoleApp/BankManagerConsoleApp/Bank/Bank.swift +++ b/BankManagerConsoleApp/BankManagerConsoleApp/Bank/Bank.swift @@ -7,39 +7,39 @@ import Foundation -struct Bank { - private let bankManager: BankManager - private let customNum: Int - - init(customNum: Int, bankManager: BankManager) { - self.customNum = customNum - self.bankManager = bankManager - } - - func openBank() { - setCustomerCount(customer: customNum) - let workTime = calulateWorkTime { - do { - try bankManager.assignBank() - } catch { - print(error.localizedDescription) - } - } - closeBank(time: workTime) - } - - private func setCustomerCount(customer: Int) { - (1...customer).forEach { bankManager.standBy(customer: Customer(banking: Banking.allCases.randomElement(), numOfPerson: $0)) } - } - - private func calulateWorkTime(work: () -> Void) -> String { - let startTime = CFAbsoluteTimeGetCurrent() - work() - let endTime = CFAbsoluteTimeGetCurrent() - return String(format: "%.2f", endTime - startTime) - } - - private func closeBank(time: String) { - print("업무가 마감되었습니다. 오늘 업무를 처리한 고객은 총 \(customNum)명이며, 총 업무시간은 \(time)초 입니다.") - } -} +//struct Bank { +// private let bankManager: BankManager +// private let customNum: Int +// +// init(customNum: Int, bankManager: BankManager) { +// self.customNum = customNum +// self.bankManager = bankManager +// } +// +// func openBank() { +// setCustomerCount(customer: customNum) +// let workTime = calulateWorkTime { +// do { +// try bankManager.assignBank() +// } catch { +// print(error.localizedDescription) +// } +// } +// closeBank(time: workTime) +// } +// +// private func setCustomerCount(customer: Int) { +// (1...customer).forEach { bankManager.standBy(customer: Customer(banking: Banking.allCases.randomElement(), numOfPerson: $0)) } +// } +// +// private func calulateWorkTime(work: () -> Void) -> String { +// let startTime = CFAbsoluteTimeGetCurrent() +// work() +// let endTime = CFAbsoluteTimeGetCurrent() +// return String(format: "%.2f", endTime - startTime) +// } +// +// private func closeBank(time: String) { +// print("업무가 마감되었습니다. 오늘 업무를 처리한 고객은 총 \(customNum)명이며, 총 업무시간은 \(time)초 입니다.") +// } +//} diff --git a/BankManagerConsoleApp/BankManagerConsoleApp/Bank/BankClerk.swift b/BankManagerConsoleApp/BankManagerConsoleApp/Bank/BankClerk.swift index f4ad5867..0e199514 100644 --- a/BankManagerConsoleApp/BankManagerConsoleApp/Bank/BankClerk.swift +++ b/BankManagerConsoleApp/BankManagerConsoleApp/Bank/BankClerk.swift @@ -7,28 +7,28 @@ import Foundation -struct BankClerk { - private var work: Banking - private var pace: Double { - switch work { - case .deposit: - return 0.7 - case .loan: - return 1.1 - } - } - - init(work: Banking) { - self.work = work - } - - func recieve(customer: Customer) { - print("\(customer.numOfPerson)번 고객 \(work.rawValue)업무 시작") - paceTime(pace) - print("\(customer.numOfPerson)번 고객 \(work.rawValue)업무 완료") - } - - private func paceTime(_ pace: Double) { - usleep(useconds_t(pace * 1000000)) - } -} +//struct BankClerk { +// private var work: Banking +// private var pace: Double { +// switch work { +// case .deposit: +// return 0.7 +// case .loan: +// return 1.1 +// } +// } +// +// init(work: Banking) { +// self.work = work +// } +// +// func recieve(customer: Customer) { +// print("\(customer.numOfPerson)번 고객 \(work.rawValue)업무 시작") +// paceTime(pace) +// print("\(customer.numOfPerson)번 고객 \(work.rawValue)업무 완료") +// } +// +// private func paceTime(_ pace: Double) { +// usleep(useconds_t(pace * 1000000)) +// } +//} diff --git a/BankManagerConsoleApp/BankManagerConsoleApp/Bank/BankManager.swift b/BankManagerConsoleApp/BankManagerConsoleApp/Bank/BankManager.swift index dbecf752..69c61662 100644 --- a/BankManagerConsoleApp/BankManagerConsoleApp/Bank/BankManager.swift +++ b/BankManagerConsoleApp/BankManagerConsoleApp/Bank/BankManager.swift @@ -8,46 +8,56 @@ import Foundation struct BankManager { private let queue = Queue(queue: LinkedList()) - private let bankClerk: [Banking: BankClerk] - private let dispatchgroup = DispatchGroup() - private let semaphore = DispatchSemaphore(value: 2) - private let loanQueue = DispatchQueue(label: "loanQueue") - private let depositQueue = DispatchQueue(label: "depositQueue", attributes: .concurrent) - - init(bankClerk: [Banking : BankClerk]) { - self.bankClerk = bankClerk - } + private let depositSemaphore = DispatchSemaphore(value: 2) + private let loanSemaphore = DispatchSemaphore(value: 1) + private let dispatchQueue = DispatchQueue.global(qos: .utility) + weak var delegate: ManageLabel? func standBy(customer: CustomerNumbering) { queue.enqueue(element: customer) } - func assignBank() throws { + func stop() { + queue.clear() + } + + func assignBank(dispatchGroup: DispatchGroup) throws { while let list = try? queue.dequeue(), let banking = list.banking { guard let customer = list as? Customer else { throw QueueError.dequeueError } switch banking { case .deposit: - assignDeposit(customer: customer) + assignDeposit(customer: customer, dispatchGroup: dispatchGroup) case .loan: - assignLoan(customer: customer) + assignLoan(customer: customer, dispatchGroup: dispatchGroup) } } - dispatchgroup.wait() } - func assignDeposit(customer: Customer) { - depositQueue.async(group: dispatchgroup) { - semaphore.wait() - bankClerk[.deposit]?.recieve(customer: customer) - semaphore.signal() + func assignDeposit(customer: Customer, dispatchGroup: DispatchGroup) { + dispatchQueue.async(group: dispatchGroup) { + depositSemaphore.wait() + recieve(customer: customer) + depositSemaphore.signal() } } - func assignLoan(customer: Customer) { - loanQueue.async(group: dispatchgroup) { - bankClerk[.loan]?.recieve(customer: customer) + func assignLoan(customer: Customer, dispatchGroup: DispatchGroup) { + dispatchQueue.async(group: dispatchGroup) { + loanSemaphore.wait() + recieve(customer: customer) + loanSemaphore.signal() } } + + func recieve(customer: Customer) { + delegate?.turn(customer: customer) + paceTime(customer.banking?.pace ?? 0) + delegate?.quit(customer: customer) + } + + private func paceTime(_ pace: Double) { + usleep(useconds_t(pace * 1000000)) + } } diff --git a/BankManagerConsoleApp/BankManagerConsoleApp/Bank/Banking.swift b/BankManagerConsoleApp/BankManagerConsoleApp/Bank/Banking.swift index b0a601e9..4867b071 100644 --- a/BankManagerConsoleApp/BankManagerConsoleApp/Bank/Banking.swift +++ b/BankManagerConsoleApp/BankManagerConsoleApp/Bank/Banking.swift @@ -10,4 +10,13 @@ import Foundation enum Banking: String, CaseIterable { case deposit = "예금" case loan = "대출" + + var pace: Double { + switch self { + case .deposit: + return 0.7 + case .loan: + return 1.1 + } + } } diff --git a/BankManagerUIApp/BankManagerUIApp.xcodeproj/project.pbxproj b/BankManagerUIApp/BankManagerUIApp.xcodeproj/project.pbxproj index 62a20a2d..7d2a15cb 100644 --- a/BankManagerUIApp/BankManagerUIApp.xcodeproj/project.pbxproj +++ b/BankManagerUIApp/BankManagerUIApp.xcodeproj/project.pbxproj @@ -7,15 +7,22 @@ objects = { /* Begin PBXBuildFile section */ + 4E37814A2B74A56E002E1B11 /* Queue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E3781412B74A56E002E1B11 /* Queue.swift */; }; + 4E37814D2B74A56E002E1B11 /* LinkedList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E3781442B74A56E002E1B11 /* LinkedList.swift */; }; + 4E37814E2B74A56E002E1B11 /* Banking.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E3781452B74A56E002E1B11 /* Banking.swift */; }; + 4E37814F2B74A56E002E1B11 /* BankManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E3781462B74A56E002E1B11 /* BankManager.swift */; }; + 4E3781502B74A56E002E1B11 /* Node.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E3781472B74A56E002E1B11 /* Node.swift */; }; + 4E3781512B74A56E002E1B11 /* QueueError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E3781482B74A56E002E1B11 /* QueueError.swift */; }; + 4E3781522B74A56E002E1B11 /* Customer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E3781492B74A56E002E1B11 /* Customer.swift */; }; + 4EE77F812B7213CE005D0F76 /* BankView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EE77F802B7213CE005D0F76 /* BankView.swift */; }; + 4EE77F9B2B721DDE005D0F76 /* CustomerLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EE77F9A2B721DDE005D0F76 /* CustomerLabel.swift */; }; C7694E3B259C3E9F0053667F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7694E3A259C3E9F0053667F /* AppDelegate.swift */; }; C7694E3D259C3E9F0053667F /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7694E3C259C3E9F0053667F /* SceneDelegate.swift */; }; - C7694E3F259C3E9F0053667F /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7694E3E259C3E9F0053667F /* ViewController.swift */; }; - C7694E42259C3E9F0053667F /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C7694E40259C3E9F0053667F /* Main.storyboard */; }; + C7694E3F259C3E9F0053667F /* BankViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7694E3E259C3E9F0053667F /* BankViewController.swift */; }; C7694E44259C3EA20053667F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C7694E43259C3EA20053667F /* Assets.xcassets */; }; C7694E47259C3EA20053667F /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C7694E45259C3EA20053667F /* LaunchScreen.storyboard */; }; C7694E52259C3EA20053667F /* BankManagerUIAppTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7694E51259C3EA20053667F /* BankManagerUIAppTests.swift */; }; C7694E5D259C3EA20053667F /* BankManagerUIAppUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7694E5C259C3EA20053667F /* BankManagerUIAppUITests.swift */; }; - C7D65D1E259C81BD005510E0 /* BankManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7D65D1D259C81BD005510E0 /* BankManager.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -36,11 +43,19 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 4E3781412B74A56E002E1B11 /* Queue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Queue.swift; sourceTree = ""; }; + 4E3781442B74A56E002E1B11 /* LinkedList.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LinkedList.swift; sourceTree = ""; }; + 4E3781452B74A56E002E1B11 /* Banking.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Banking.swift; path = ../../../BankManagerConsoleApp/BankManagerConsoleApp/Bank/Banking.swift; sourceTree = ""; }; + 4E3781462B74A56E002E1B11 /* BankManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BankManager.swift; path = ../../../BankManagerConsoleApp/BankManagerConsoleApp/Bank/BankManager.swift; sourceTree = ""; }; + 4E3781472B74A56E002E1B11 /* Node.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Node.swift; sourceTree = ""; }; + 4E3781482B74A56E002E1B11 /* QueueError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QueueError.swift; sourceTree = ""; }; + 4E3781492B74A56E002E1B11 /* Customer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Customer.swift; path = ../../../BankManagerConsoleApp/BankManagerConsoleApp/Bank/Customer.swift; sourceTree = ""; }; + 4EE77F802B7213CE005D0F76 /* BankView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BankView.swift; sourceTree = ""; }; + 4EE77F9A2B721DDE005D0F76 /* CustomerLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomerLabel.swift; sourceTree = ""; }; C7694E37259C3E9F0053667F /* BankManagerUIApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = BankManagerUIApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; C7694E3A259C3E9F0053667F /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; C7694E3C259C3E9F0053667F /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; - C7694E3E259C3E9F0053667F /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; - C7694E41259C3E9F0053667F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + C7694E3E259C3E9F0053667F /* BankViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BankViewController.swift; sourceTree = ""; }; C7694E43259C3EA20053667F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; C7694E46259C3EA20053667F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; C7694E48259C3EA20053667F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -50,7 +65,6 @@ C7694E58259C3EA20053667F /* BankManagerUIAppUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = BankManagerUIAppUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; C7694E5C259C3EA20053667F /* BankManagerUIAppUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BankManagerUIAppUITests.swift; sourceTree = ""; }; C7694E5E259C3EA20053667F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - C7D65D1D259C81BD005510E0 /* BankManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BankManager.swift; path = ../../BankManager.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -78,6 +92,45 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 4E3781402B74A55B002E1B11 /* Model */ = { + isa = PBXGroup; + children = ( + 4E3781532B74D03F002E1B11 /* DataSource */, + 4E3781452B74A56E002E1B11 /* Banking.swift */, + 4E3781462B74A56E002E1B11 /* BankManager.swift */, + 4E3781492B74A56E002E1B11 /* Customer.swift */, + ); + path = Model; + sourceTree = ""; + }; + 4E3781532B74D03F002E1B11 /* DataSource */ = { + isa = PBXGroup; + children = ( + 4E3781442B74A56E002E1B11 /* LinkedList.swift */, + 4E3781472B74A56E002E1B11 /* Node.swift */, + 4E3781412B74A56E002E1B11 /* Queue.swift */, + 4E3781482B74A56E002E1B11 /* QueueError.swift */, + ); + path = DataSource; + sourceTree = ""; + }; + 4EE77F822B721553005D0F76 /* View */ = { + isa = PBXGroup; + children = ( + 4EE77F802B7213CE005D0F76 /* BankView.swift */, + 4EE77F9A2B721DDE005D0F76 /* CustomerLabel.swift */, + ); + path = View; + sourceTree = ""; + }; + 4EE77F842B7215BF005D0F76 /* Controller */ = { + isa = PBXGroup; + children = ( + C7694E3E259C3E9F0053667F /* BankViewController.swift */, + ); + path = Controller; + sourceTree = ""; + }; C7694E2E259C3E9F0053667F = { isa = PBXGroup; children = ( @@ -101,11 +154,11 @@ C7694E39259C3E9F0053667F /* BankManagerUIApp */ = { isa = PBXGroup; children = ( - C7D65D1D259C81BD005510E0 /* BankManager.swift */, + 4E3781402B74A55B002E1B11 /* Model */, + 4EE77F822B721553005D0F76 /* View */, + 4EE77F842B7215BF005D0F76 /* Controller */, C7694E3A259C3E9F0053667F /* AppDelegate.swift */, C7694E3C259C3E9F0053667F /* SceneDelegate.swift */, - C7694E3E259C3E9F0053667F /* ViewController.swift */, - C7694E40259C3E9F0053667F /* Main.storyboard */, C7694E43259C3EA20053667F /* Assets.xcassets */, C7694E45259C3EA20053667F /* LaunchScreen.storyboard */, C7694E48259C3EA20053667F /* Info.plist */, @@ -236,7 +289,6 @@ files = ( C7694E47259C3EA20053667F /* LaunchScreen.storyboard in Resources */, C7694E44259C3EA20053667F /* Assets.xcassets in Resources */, - C7694E42259C3E9F0053667F /* Main.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -261,10 +313,18 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - C7694E3F259C3E9F0053667F /* ViewController.swift in Sources */, + 4E37814D2B74A56E002E1B11 /* LinkedList.swift in Sources */, + 4E3781522B74A56E002E1B11 /* Customer.swift in Sources */, + 4E3781512B74A56E002E1B11 /* QueueError.swift in Sources */, + 4EE77F812B7213CE005D0F76 /* BankView.swift in Sources */, + 4E37814A2B74A56E002E1B11 /* Queue.swift in Sources */, + 4E3781502B74A56E002E1B11 /* Node.swift in Sources */, + 4EE77F9B2B721DDE005D0F76 /* CustomerLabel.swift in Sources */, + C7694E3F259C3E9F0053667F /* BankViewController.swift in Sources */, C7694E3B259C3E9F0053667F /* AppDelegate.swift in Sources */, + 4E37814E2B74A56E002E1B11 /* Banking.swift in Sources */, C7694E3D259C3E9F0053667F /* SceneDelegate.swift in Sources */, - C7D65D1E259C81BD005510E0 /* BankManager.swift in Sources */, + 4E37814F2B74A56E002E1B11 /* BankManager.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -300,14 +360,6 @@ /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ - C7694E40259C3E9F0053667F /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - C7694E41259C3E9F0053667F /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; C7694E45259C3EA20053667F /* LaunchScreen.storyboard */ = { isa = PBXVariantGroup; children = ( diff --git a/BankManagerUIApp/BankManagerUIApp/Base.lproj/Main.storyboard b/BankManagerUIApp/BankManagerUIApp/Base.lproj/Main.storyboard deleted file mode 100644 index ce80ec92..00000000 --- a/BankManagerUIApp/BankManagerUIApp/Base.lproj/Main.storyboard +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/BankManagerUIApp/BankManagerUIApp/Controller/BankViewController.swift b/BankManagerUIApp/BankManagerUIApp/Controller/BankViewController.swift new file mode 100644 index 00000000..0aba89db --- /dev/null +++ b/BankManagerUIApp/BankManagerUIApp/Controller/BankViewController.swift @@ -0,0 +1,113 @@ +// +// BankManagerUIApp - ViewController.swift +// Created by yagom. +// Copyright © yagom academy. All rights reserved. +// + +import UIKit + +protocol ManageLabel: AnyObject { + func turn(customer: Customer) + func quit(customer: Customer) +} + +final class BankViewController: UIViewController { + + private let bankView = BankView() + private var timer: Timer? + private var initialTime = 0.000 + private var bankManager = BankManager() + private var count = 1 + private let dispatchGroup = DispatchGroup() + private var isRunning = false + + override func loadView() { + view = bankView + } + + override func viewDidLoad() { + super.viewDidLoad() + bankView.addCustomerButton.addTarget(self, action: #selector(addCustomerButtonTapped), for: .touchUpInside) + bankView.resetButton.addTarget(self, action: #selector(resetButtonTapped), for: .touchUpInside) + } + + @objc func addCustomerButtonTapped() { + for num in count...count + 9 { + let customer = Customer(banking: Banking.allCases.randomElement(), numOfPerson: num) + bankManager.standBy(customer: customer) + bankView.waitStackView.addArrangedSubview(CustomerLabel(customer: customer)) + } + + count += 10 + + bankManager.delegate = self + do { + try bankManager.assignBank(dispatchGroup: dispatchGroup) + } catch { + print(error) + } + guard isRunning == false else { return } + timer = Timer.scheduledTimer(timeInterval: 0.001, target: self, selector: #selector(runningTimer), userInfo: nil, repeats: true) + + guard let timer = timer else { return } + RunLoop.main.add(timer, forMode: .common) + isRunning = true + + dispatchGroup.notify(queue: DispatchQueue.main) { + self.timer?.invalidate() + self.isRunning = false + } + } + + @objc func resetButtonTapped() { + bankManager.stop() + + for subView in bankView.waitStackView.arrangedSubviews { + subView.removeFromSuperview() + } + for subeView in bankView.taskStackView.arrangedSubviews { + subeView.removeFromSuperview() + } + + timer?.invalidate() + timer = nil + initialTime = 0.000 + bankView.taskTimeLabel.text = "업무시간 - 00:00:000" + + count = 1 + } + + @objc func runningTimer() { + let minutes = Int(initialTime) / 60 + let seconds = Int(initialTime) % 60 + let milliSeconds = Int((initialTime.truncatingRemainder(dividingBy: 1)) * 1000) + + bankView.taskTimeLabel.text = String(format: "업무시간 - %02d:%02d:%03d", minutes, seconds, milliSeconds) + initialTime += 0.001 + } +} + +extension BankViewController: ManageLabel { + + func turn(customer: Customer) { + DispatchQueue.main.async { + self.removeLabel(view: self.bankView.waitStackView, customer: customer) + self.bankView.taskStackView.addArrangedSubview(CustomerLabel(customer: customer)) + } + } + + func quit(customer: Customer) { + DispatchQueue.main.async { + self.removeLabel(view: self.bankView.taskStackView, customer: customer) + } + } + + private func removeLabel(view: UIStackView, customer: Customer) { + let customerLabel = view.arrangedSubviews.first { view in + guard let customerLabelNumber = view as? CustomerLabel else { return false } + return customerLabelNumber.customer.numOfPerson == customer.numOfPerson + } + customerLabel?.removeFromSuperview() + } +} + diff --git a/BankManagerUIApp/BankManagerUIApp/Info.plist b/BankManagerUIApp/BankManagerUIApp/Info.plist index 5b531f7b..2688b32b 100644 --- a/BankManagerUIApp/BankManagerUIApp/Info.plist +++ b/BankManagerUIApp/BankManagerUIApp/Info.plist @@ -33,8 +33,6 @@ Default Configuration UISceneDelegateClassName $(PRODUCT_MODULE_NAME).SceneDelegate - UISceneStoryboardFile - Main @@ -43,8 +41,6 @@ UILaunchStoryboardName LaunchScreen - UIMainStoryboardFile - Main UIRequiredDeviceCapabilities armv7 diff --git a/BankManagerConsoleApp/BankManagerConsoleApp/LinkedList.swift b/BankManagerUIApp/BankManagerUIApp/Model/DataSource/LinkedList.swift similarity index 100% rename from BankManagerConsoleApp/BankManagerConsoleApp/LinkedList.swift rename to BankManagerUIApp/BankManagerUIApp/Model/DataSource/LinkedList.swift diff --git a/BankManagerConsoleApp/BankManagerConsoleApp/Node.swift b/BankManagerUIApp/BankManagerUIApp/Model/DataSource/Node.swift similarity index 100% rename from BankManagerConsoleApp/BankManagerConsoleApp/Node.swift rename to BankManagerUIApp/BankManagerUIApp/Model/DataSource/Node.swift diff --git a/BankManagerConsoleApp/BankManagerConsoleApp/Queue.swift b/BankManagerUIApp/BankManagerUIApp/Model/DataSource/Queue.swift similarity index 100% rename from BankManagerConsoleApp/BankManagerConsoleApp/Queue.swift rename to BankManagerUIApp/BankManagerUIApp/Model/DataSource/Queue.swift diff --git a/BankManagerConsoleApp/BankManagerConsoleApp/QueueError.swift b/BankManagerUIApp/BankManagerUIApp/Model/DataSource/QueueError.swift similarity index 100% rename from BankManagerConsoleApp/BankManagerConsoleApp/QueueError.swift rename to BankManagerUIApp/BankManagerUIApp/Model/DataSource/QueueError.swift diff --git a/BankManagerUIApp/BankManagerUIApp/SceneDelegate.swift b/BankManagerUIApp/BankManagerUIApp/SceneDelegate.swift index 63d2d2a1..52a087fe 100644 --- a/BankManagerUIApp/BankManagerUIApp/SceneDelegate.swift +++ b/BankManagerUIApp/BankManagerUIApp/SceneDelegate.swift @@ -12,40 +12,21 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { - // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. - // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. - // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). - guard let _ = (scene as? UIWindowScene) else { return } + guard let windowScene = (scene as? UIWindowScene) else { return } + window = UIWindow(windowScene: windowScene) + + window?.rootViewController = BankViewController() + window?.makeKeyAndVisible() } - func sceneDidDisconnect(_ scene: UIScene) { - // Called as the scene is being released by the system. - // This occurs shortly after the scene enters the background, or when its session is discarded. - // Release any resources associated with this scene that can be re-created the next time the scene connects. - // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead). - } - - func sceneDidBecomeActive(_ scene: UIScene) { - // Called when the scene has moved from an inactive state to an active state. - // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. - } + func sceneDidDisconnect(_ scene: UIScene) { } - func sceneWillResignActive(_ scene: UIScene) { - // Called when the scene will move from an active state to an inactive state. - // This may occur due to temporary interruptions (ex. an incoming phone call). - } + func sceneDidBecomeActive(_ scene: UIScene) { } - func sceneWillEnterForeground(_ scene: UIScene) { - // Called as the scene transitions from the background to the foreground. - // Use this method to undo the changes made on entering the background. - } - - func sceneDidEnterBackground(_ scene: UIScene) { - // Called as the scene transitions from the foreground to the background. - // Use this method to save data, release shared resources, and store enough scene-specific state information - // to restore the scene back to its current state. - } + func sceneWillResignActive(_ scene: UIScene) { } + func sceneWillEnterForeground(_ scene: UIScene) { } + func sceneDidEnterBackground(_ scene: UIScene) { } } diff --git a/BankManagerUIApp/BankManagerUIApp/View/BankView.swift b/BankManagerUIApp/BankManagerUIApp/View/BankView.swift new file mode 100644 index 00000000..9b477f5f --- /dev/null +++ b/BankManagerUIApp/BankManagerUIApp/View/BankView.swift @@ -0,0 +1,157 @@ +// +// BankView.swift +// BankManagerUIApp +// +// Created by 미르, 희동 on 2/6/24. +// + +import UIKit + +extension UIButton { + convenience init(title: String, titleColor: UIColor) { + self.init() + + self.setTitleColor(titleColor, for: .normal) + self.setTitle(title, for: .normal) + self.translatesAutoresizingMaskIntoConstraints = false + } +} + +extension UILabel { + convenience init(text: String, font: UIFont = .systemFont(ofSize: 20), textColor: UIColor, backgroundColor: UIColor, textAlignment: NSTextAlignment = .center) { + self.init() + + self.text = text + self.font = font + self.textColor = textColor + self.backgroundColor = backgroundColor + self.textAlignment = textAlignment + self.translatesAutoresizingMaskIntoConstraints = false + } +} + +extension UIStackView { + convenience init(axis: NSLayoutConstraint.Axis, distribution: UIStackView.Distribution, alignment: UIStackView.Alignment, sapcing: CGFloat = 0, subViews: [UIView] = []) { + self.init() + + self.axis = axis + self.distribution = distribution + self.alignment = alignment + self.spacing = spacing + self .translatesAutoresizingMaskIntoConstraints = false + for subView in subViews { + self.addArrangedSubview(subView) + } + } +} + +class BankView: UIView { + let addCustomerButton: UIButton = { + let button = UIButton(title: "고객 10명 추가", titleColor: .blue) + + return button + }() + + let resetButton: UIButton = { + let button = UIButton(title: "초기화", titleColor: .red) + return button + }() + + private lazy var buttonStackView: UIStackView = { + let stackView = UIStackView(axis: .horizontal, distribution: .fillEqually, alignment: .fill, sapcing: 2, subViews: [addCustomerButton, resetButton]) + + return stackView + }() + + let taskTimeLabel: UILabel = { + let label = UILabel(text: "업무시간 - 00:00:000", textColor: .black, backgroundColor: .clear) + + return label + }() + + private let waitLabel: UILabel = { + let label = UILabel(text: "대기중",font: .preferredFont(forTextStyle: .largeTitle), textColor: .white, backgroundColor: .systemGreen) + + return label + }() + + private let taskLabel: UILabel = { + let label = UILabel(text: "업무중",font: .preferredFont(forTextStyle: .largeTitle), textColor: .white, backgroundColor: .systemIndigo) + + return label + }() + + private lazy var labelStackView: UIStackView = { + let stackView = UIStackView(axis: .horizontal, distribution: .fillEqually, alignment: .fill, subViews: [waitLabel, taskLabel]) + + return stackView + }() + + private lazy var headerStackView: UIStackView = { + let stackView = UIStackView(axis: .vertical, distribution: .fillEqually, alignment: .fill, subViews: [buttonStackView, taskTimeLabel, labelStackView]) + + return stackView + }() + + lazy var waitStackView: UIStackView = { + let stackView = UIStackView(axis: .vertical, distribution: .fill, alignment: .fill, sapcing: 10) + + return stackView + }() + + lazy var waitTableView: UITableView = { + let tableView = UITableView() + tableView.addSubview(waitStackView) + + return tableView + }() + + lazy var taskStackView: UIStackView = { + let stackView = UIStackView(axis: .vertical, distribution: .fill, alignment: .fill, sapcing: 10) + + return stackView + }() + + lazy var taskTableView: UITableView = { + let tableView = UITableView() + tableView.addSubview(taskStackView) + + return tableView + }() + + private lazy var footerStackView: UIStackView = { + let stackView = UIStackView(axis: .horizontal, distribution: .fillEqually, alignment: .fill, subViews: [waitTableView, taskTableView]) + + return stackView + }() + + override init(frame: CGRect) { + super.init(frame: frame) + backgroundColor = .white + setupStackView() + setConstraint() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func setupStackView() { + self.addSubview(headerStackView) + self.addSubview(footerStackView) + } + + private func setConstraint() { + + NSLayoutConstraint.activate([ + headerStackView.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor), + headerStackView.leadingAnchor.constraint(equalTo: safeAreaLayoutGuide.leadingAnchor), + headerStackView.trailingAnchor.constraint(equalTo: safeAreaLayoutGuide.trailingAnchor), + + footerStackView.topAnchor.constraint(equalTo: headerStackView.bottomAnchor), + footerStackView.leadingAnchor.constraint(equalTo: safeAreaLayoutGuide.leadingAnchor), + footerStackView.trailingAnchor.constraint(equalTo: safeAreaLayoutGuide.trailingAnchor), + footerStackView.bottomAnchor.constraint(equalTo: safeAreaLayoutGuide.bottomAnchor) + ]) + } +} diff --git a/BankManagerUIApp/BankManagerUIApp/View/CustomerLabel.swift b/BankManagerUIApp/BankManagerUIApp/View/CustomerLabel.swift new file mode 100644 index 00000000..f682c26e --- /dev/null +++ b/BankManagerUIApp/BankManagerUIApp/View/CustomerLabel.swift @@ -0,0 +1,36 @@ +// +// CustomerLabel.swift +// BankManagerUIApp +// +// Created by 미르, 희동 on 2/6/24. +// + +import UIKit + +class CustomerLabel: UILabel { + var customer: Customer + + init(customer: Customer) { + self.customer = customer + super.init(frame: .zero) + self.updateLabel() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func updateLabel() { + self.text = "\(customer.numOfPerson)번 - \(customer.banking?.rawValue ?? "")" + + switch customer.banking { + case .deposit: + self.textColor = .black + case .loan: + self.textColor = .purple + case .none: + return + } + } + +} diff --git a/BankManagerUIApp/BankManagerUIApp/ViewController.swift b/BankManagerUIApp/BankManagerUIApp/ViewController.swift deleted file mode 100644 index a3182156..00000000 --- a/BankManagerUIApp/BankManagerUIApp/ViewController.swift +++ /dev/null @@ -1,18 +0,0 @@ -// -// BankManagerUIApp - ViewController.swift -// Created by yagom. -// Copyright © yagom academy. All rights reserved. -// - -import UIKit - -class ViewController: UIViewController { - - override func viewDidLoad() { - super.viewDidLoad() - // Do any additional setup after loading the view. - } - - -} -