diff --git a/BankManager.swift b/BankManager.swift index b2fc7e01..c287181d 100644 --- a/BankManager.swift +++ b/BankManager.swift @@ -1,62 +1,52 @@ import Foundation final class BankManager { - private let customerCount: Int - private let depositTellers: Tellers - private let loanTellers: Tellers + private var customerCount: Int = 0 private let depositCustomerQueue = Queue() private let loanCustomerQueue = Queue() - private var startTime: Date? + var depositTellers: Tellers + var loanTellers: Tellers + weak var delegate: BankUIDelegate? + init(depositTellerCount: Int, loanTellerCount: Int) { - self.customerCount = Int.random(in: 10...30) self.depositTellers = Tellers(tellerCount: depositTellerCount, tellerType: .Deposit) self.loanTellers = Tellers(tellerCount: loanTellerCount, tellerType: .Loan) } - func openBank() { - startTime = Date() - createCustomerQueue(customerCount: customerCount) - startTask() - } - - func finishTask() { - let endTime = Date() - guard let startTime = startTime else { return } - let time = endTime.timeIntervalSince(startTime) - let totalSecond = String(format: "%.2f", time) - print("업무가 마감되었습니다. 오늘 업무를 처리한 고객은 총 \(customerCount)명이며, 총 업무시간은 \(totalSecond)초 입니다.") - } - - private func createCustomerQueue(customerCount: Int) { - for n in 1...customerCount { + func createCustomerQueue() { + for n in 1...10 { guard let work = TypeOfWork(rawValue: Int.random(in: 0...1)) else { return } switch work { + case .Deposit: - depositCustomerQueue.enqueue(data: n) + depositCustomerQueue.enqueue(data: n + customerCount) + delegate?.addTaskLabel(type: .Deposit, number: n + customerCount, textColor: .black) case .Loan: - loanCustomerQueue.enqueue(data: n) + loanCustomerQueue.enqueue(data: n + customerCount) + delegate?.addTaskLabel(type: .Loan, number: n + customerCount, textColor: .orange) } } + customerCount += 10 } - private func startTask() { + func startTask() { let depositWork = (depositTellers, depositCustomerQueue) let loanWork = (loanTellers, loanCustomerQueue) - let group = DispatchGroup() [depositWork, loanWork].forEach { (tellers, queue) in - group.enter() - DispatchQueue.global().async { + DispatchQueue.global(qos: .utility ).async { tellers.doTask(queue: queue) - group.leave() } } - - group.wait() } + func reset() { + customerCount = 0 + depositCustomerQueue.clear() + loanCustomerQueue.clear() + } } diff --git a/BankManagerConsoleApp/BankManagerConsoleApp/Tellers.swift b/BankManagerConsoleApp/BankManagerConsoleApp/Tellers.swift index ce3386bb..b61ece5a 100644 --- a/BankManagerConsoleApp/BankManagerConsoleApp/Tellers.swift +++ b/BankManagerConsoleApp/BankManagerConsoleApp/Tellers.swift @@ -1,40 +1,37 @@ import Foundation + struct Tellers { private let tellerCount: Int - private let tellerType: TypeOfWork + let tellerType: TypeOfWork + private let semaphore: DispatchSemaphore + weak var delegate: BankUIDelegate? init(tellerCount: Int, tellerType: TypeOfWork) { self.tellerCount = tellerCount self.tellerType = tellerType + self.semaphore = DispatchSemaphore(value: tellerCount) } - + func doTask(queue: Queue) { - let name = tellerType.name let time = tellerType.time - let semaphore = DispatchSemaphore(value: tellerCount) let group = DispatchGroup() - var workingTellerCount = 0 while !queue.isEmpty() { + + guard let data = queue.dequeue() else { return } + + group.enter() semaphore.wait() - guard let data = queue.dequeue() else { + DispatchQueue.global().async { + delegate?.changeToLabelState(tellerType: tellerType, data: data) + + usleep(time) + + delegate?.removeLabel(data: data) semaphore.signal() - return - } - - if workingTellerCount < tellerCount { - group.enter() - DispatchQueue.global().async { - workingTellerCount += 1 - print("\(name) 은행원 \(data)번 고객 \(name)업무 시작") - usleep(time) - print("\(name) 은행원 \(data)번 고객 \(name)업무 완료") - workingTellerCount -= 1 - semaphore.signal() - group.leave() - } + group.leave() } } group.wait() diff --git a/BankManagerUIApp/BankManagerUIApp.xcodeproj/project.pbxproj b/BankManagerUIApp/BankManagerUIApp.xcodeproj/project.pbxproj index 62a20a2d..c6d4e051 100644 --- a/BankManagerUIApp/BankManagerUIApp.xcodeproj/project.pbxproj +++ b/BankManagerUIApp/BankManagerUIApp.xcodeproj/project.pbxproj @@ -7,15 +7,19 @@ objects = { /* Begin PBXBuildFile section */ + 6B5F8FC42B03305F00D23FF8 /* Protocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B5F8FC32B03305F00D23FF8 /* Protocol.swift */; }; + 6BAA0FCD2B05B077007579A1 /* BankView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BAA0FCC2B05B077007579A1 /* BankView.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 */; }; 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 */; }; + D0D1B85B2AFDEC140017D3A6 /* Queue.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0D1B85A2AFDEC140017D3A6 /* Queue.swift */; }; + D0D1B85D2AFDEC600017D3A6 /* Tellers.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0D1B85C2AFDEC600017D3A6 /* Tellers.swift */; }; + D0D1B85F2AFDEC670017D3A6 /* TypeOfWork.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0D1B85E2AFDEC670017D3A6 /* TypeOfWork.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -36,11 +40,12 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 6B5F8FC32B03305F00D23FF8 /* Protocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Protocol.swift; sourceTree = ""; }; + 6BAA0FCC2B05B077007579A1 /* BankView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BankView.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 = ""; }; 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 = ""; }; @@ -51,6 +56,9 @@ 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 = ""; }; + D0D1B85A2AFDEC140017D3A6 /* Queue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Queue.swift; path = ../BankManagerConsoleApp/BankManagerConsoleApp/Queue.swift; sourceTree = ""; }; + D0D1B85C2AFDEC600017D3A6 /* Tellers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Tellers.swift; path = ../BankManagerConsoleApp/BankManagerConsoleApp/Tellers.swift; sourceTree = ""; }; + D0D1B85E2AFDEC670017D3A6 /* TypeOfWork.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TypeOfWork.swift; path = ../BankManagerConsoleApp/BankManagerConsoleApp/TypeOfWork.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -81,6 +89,9 @@ C7694E2E259C3E9F0053667F = { isa = PBXGroup; children = ( + D0D1B85E2AFDEC670017D3A6 /* TypeOfWork.swift */, + D0D1B85C2AFDEC600017D3A6 /* Tellers.swift */, + D0D1B85A2AFDEC140017D3A6 /* Queue.swift */, C7694E39259C3E9F0053667F /* BankManagerUIApp */, C7694E50259C3EA20053667F /* BankManagerUIAppTests */, C7694E5B259C3EA20053667F /* BankManagerUIAppUITests */, @@ -105,7 +116,8 @@ C7694E3A259C3E9F0053667F /* AppDelegate.swift */, C7694E3C259C3E9F0053667F /* SceneDelegate.swift */, C7694E3E259C3E9F0053667F /* ViewController.swift */, - C7694E40259C3E9F0053667F /* Main.storyboard */, + 6BAA0FCC2B05B077007579A1 /* BankView.swift */, + 6B5F8FC32B03305F00D23FF8 /* Protocol.swift */, C7694E43259C3EA20053667F /* Assets.xcassets */, C7694E45259C3EA20053667F /* LaunchScreen.storyboard */, C7694E48259C3EA20053667F /* Info.plist */, @@ -236,7 +248,6 @@ files = ( C7694E47259C3EA20053667F /* LaunchScreen.storyboard in Resources */, C7694E44259C3EA20053667F /* Assets.xcassets in Resources */, - C7694E42259C3E9F0053667F /* Main.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -261,10 +272,15 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + D0D1B85B2AFDEC140017D3A6 /* Queue.swift in Sources */, C7694E3F259C3E9F0053667F /* ViewController.swift in Sources */, C7694E3B259C3E9F0053667F /* AppDelegate.swift in Sources */, + 6B5F8FC42B03305F00D23FF8 /* Protocol.swift in Sources */, + D0D1B85F2AFDEC670017D3A6 /* TypeOfWork.swift in Sources */, C7694E3D259C3E9F0053667F /* SceneDelegate.swift in Sources */, + 6BAA0FCD2B05B077007579A1 /* BankView.swift in Sources */, C7D65D1E259C81BD005510E0 /* BankManager.swift in Sources */, + D0D1B85D2AFDEC600017D3A6 /* Tellers.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -300,14 +316,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/BankView.swift b/BankManagerUIApp/BankManagerUIApp/BankView.swift new file mode 100644 index 00000000..8c622e69 --- /dev/null +++ b/BankManagerUIApp/BankManagerUIApp/BankView.swift @@ -0,0 +1,168 @@ +// +// BankView.swift +// BankManagerUIApp +// +// Created by 최승범 on 2023/11/16. +// + +import UIKit + +final class BankView: UIView { + + private lazy var mainStackView: UIStackView = configureVerticalStackView() + + private lazy var buttonStackView: UIStackView = configureHorizontalStackView() + lazy var addCustomerButton: UIButton = configureButton(title: "고객 10명 추가", color: .blue) + lazy var resetButton: UIButton = configureButton(title: "초기화", color: .red) + + lazy var timerTitleLabel: UILabel = { + let label = UILabel() + label.text = "00 : 00 : 000" + label.textAlignment = .center + label.font = UIFont.monospacedSystemFont(ofSize: 24, weight: .regular) + return label + }() + + private lazy var titleStackView: UIStackView = configureHorizontalStackView() + private lazy var readyTitleLabel: UILabel = configureTitleLabel(text: "대기중", backgroundColor: .systemGreen) + private lazy var runningTitleLabel: UILabel = configureTitleLabel(text: "업무중", backgroundColor: .systemBlue) + + private lazy var listStackView: UIStackView = { + let view = configureHorizontalStackView() + view.alignment = .fill + return view + }() + + private lazy var readyListView: UIView = { + let view = UIView() + return view + }() + + private lazy var runningListView: UIView = { + let view = UIView() + return view + }() + + private lazy var readyListScrollView: UIScrollView = { + let view = UIScrollView() + view.bounces = false + return view + }() + + private lazy var runningListScrollView: UIScrollView = { + let view = UIScrollView() + view.bounces = false + return view + }() + + lazy var readyListStackView: UIStackView = configureVerticalStackView() + + lazy var runningListStackView: UIStackView = configureVerticalStackView() + + func configureVerticalStackView() -> UIStackView { + let view = UIStackView() + view.axis = .vertical + view.spacing = 16 + return view + } + + func configureHorizontalStackView() -> UIStackView { + let view = UIStackView() + view.axis = .horizontal + view.distribution = .fillEqually + return view + } + + func configureTitleLabel(text: String, backgroundColor: UIColor) -> UILabel { + let label = UILabel() + label.text = text + label.textAlignment = .center + label.backgroundColor = backgroundColor + label.textColor = .white + label.font = .systemFont(ofSize: 40) + return label + } + + func configureButton(title: String, color: UIColor) -> UIButton { + let button = UIButton() + button.setTitle(title, for: .normal) + button.setTitleColor(color, for: .normal) + return button + } + + func configureTaskLabel(type: TypeOfWork, number: Int, textColor: UIColor) -> UILabel { + let label = UILabel() + label.text = "\(number) - \(type.name)" + label.textAlignment = .center + label.textColor = textColor + label.font = .systemFont(ofSize: 24) + label.tag = number + return label + } + + + func configure() { + self.addSubview(mainStackView) + mainStackView.addArrangedSubview(buttonStackView) + mainStackView.addArrangedSubview(timerTitleLabel) + mainStackView.addArrangedSubview(titleStackView) + mainStackView.addArrangedSubview(listStackView) + + buttonStackView.addArrangedSubview(addCustomerButton) + buttonStackView.addArrangedSubview(resetButton) + + titleStackView.addArrangedSubview(readyTitleLabel) + titleStackView.addArrangedSubview(runningTitleLabel) + + listStackView.addArrangedSubview(readyListView) + listStackView.addArrangedSubview(runningListView) + + readyListView.addSubview(readyListScrollView) + runningListView.addSubview(runningListScrollView) + + readyListScrollView.addSubview(readyListStackView) + runningListScrollView.addSubview(runningListStackView) + } + + func setupAutoLayout() { + let safeArea = self + mainStackView.translatesAutoresizingMaskIntoConstraints = false + + mainStackView.topAnchor.constraint(equalTo: safeArea.topAnchor).isActive = true + mainStackView.bottomAnchor.constraint(equalTo: safeArea.bottomAnchor).isActive = true + mainStackView.leadingAnchor.constraint(equalTo: safeArea.leadingAnchor).isActive = true + mainStackView.trailingAnchor.constraint(equalTo: safeArea.trailingAnchor).isActive = true + + readyListScrollView.translatesAutoresizingMaskIntoConstraints = false + + readyListScrollView.topAnchor.constraint(equalTo: readyListView.topAnchor).isActive = true + readyListScrollView.bottomAnchor.constraint(equalTo: readyListView.bottomAnchor).isActive = true + readyListScrollView.leadingAnchor.constraint(equalTo: readyListView.leadingAnchor).isActive = true + readyListScrollView.trailingAnchor.constraint(equalTo: readyListView.trailingAnchor).isActive = true + + runningListScrollView.translatesAutoresizingMaskIntoConstraints = false + + runningListScrollView.topAnchor.constraint(equalTo: runningListView.topAnchor).isActive = true + runningListScrollView.bottomAnchor.constraint(equalTo: runningListView.bottomAnchor).isActive = true + runningListScrollView.leadingAnchor.constraint(equalTo: runningListView.leadingAnchor).isActive = true + runningListScrollView.trailingAnchor.constraint(equalTo: runningListView.trailingAnchor).isActive = true + + readyListStackView.translatesAutoresizingMaskIntoConstraints = false + + readyListStackView.topAnchor.constraint(equalTo: readyListScrollView.topAnchor).isActive = true + readyListStackView.bottomAnchor.constraint(equalTo: readyListScrollView.bottomAnchor).isActive = true + readyListStackView.leadingAnchor.constraint(equalTo: readyListScrollView.leadingAnchor).isActive = true + readyListStackView.trailingAnchor.constraint(equalTo: readyListScrollView.trailingAnchor).isActive = true + readyListStackView.widthAnchor.constraint(equalTo: readyListScrollView.widthAnchor).isActive = true + + runningListStackView.translatesAutoresizingMaskIntoConstraints = false + + runningListStackView.topAnchor.constraint(equalTo: runningListScrollView.topAnchor).isActive = true + runningListStackView.bottomAnchor.constraint(equalTo: runningListScrollView.bottomAnchor).isActive = true + runningListStackView.leadingAnchor.constraint(equalTo: runningListScrollView.leadingAnchor).isActive = true + runningListStackView.trailingAnchor.constraint(equalTo: runningListScrollView.trailingAnchor).isActive = true + runningListStackView.widthAnchor.constraint(equalTo: runningListScrollView.widthAnchor).isActive = true + + } +} + diff --git a/BankManagerUIApp/BankManagerUIApp/Base.lproj/LaunchScreen.storyboard b/BankManagerUIApp/BankManagerUIApp/Base.lproj/LaunchScreen.storyboard index 865e9329..ca535dbf 100644 --- a/BankManagerUIApp/BankManagerUIApp/Base.lproj/LaunchScreen.storyboard +++ b/BankManagerUIApp/BankManagerUIApp/Base.lproj/LaunchScreen.storyboard @@ -1,8 +1,11 @@ - - + + + - + + + @@ -11,10 +14,10 @@ - + - + @@ -22,4 +25,9 @@ + + + + + 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/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/BankManagerUIApp/BankManagerUIApp/Protocol.swift b/BankManagerUIApp/BankManagerUIApp/Protocol.swift new file mode 100644 index 00000000..8da9b55c --- /dev/null +++ b/BankManagerUIApp/BankManagerUIApp/Protocol.swift @@ -0,0 +1,13 @@ + +import UIKit + + +protocol BankUIDelegate: AnyObject { + func addTaskLabel(type: TypeOfWork, number: Int, textColor: UIColor) + + func changeToLabelState(tellerType: TypeOfWork,data: Int) + + func removeLabel(data: Int) +} + + diff --git a/BankManagerUIApp/BankManagerUIApp/SceneDelegate.swift b/BankManagerUIApp/BankManagerUIApp/SceneDelegate.swift index 63d2d2a1..25e4681f 100644 --- a/BankManagerUIApp/BankManagerUIApp/SceneDelegate.swift +++ b/BankManagerUIApp/BankManagerUIApp/SceneDelegate.swift @@ -10,12 +10,14 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? - 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 = ViewController() + window?.makeKeyAndVisible() } func sceneDidDisconnect(_ scene: UIScene) { diff --git a/BankManagerUIApp/BankManagerUIApp/ViewController.swift b/BankManagerUIApp/BankManagerUIApp/ViewController.swift index a3182156..94d80a58 100644 --- a/BankManagerUIApp/BankManagerUIApp/ViewController.swift +++ b/BankManagerUIApp/BankManagerUIApp/ViewController.swift @@ -4,15 +4,118 @@ // Copyright © yagom academy. All rights reserved. // -import UIKit -class ViewController: UIViewController { +import UIKit +final class ViewController: UIViewController, BankUIDelegate { + private let bankManager = BankManager(depositTellerCount: 2, loanTellerCount: 1) + + private var timer: Timer = Timer() + private var time: Double = 0 + + private let bankView = BankView() + override func viewDidLoad() { super.viewDidLoad() - // Do any additional setup after loading the view. + + bankManager.delegate = self + bankManager.depositTellers.delegate = self + bankManager.loanTellers.delegate = self + + view.backgroundColor = .white + view.addSubview(bankView) + + configureBankView() } + + private func startTimer() { + if !timer.isValid { + timer = Timer.scheduledTimer(timeInterval: 0.001, target: self, selector: #selector(setTimerLabel), userInfo: nil, repeats: true) + RunLoop.main.add(timer, forMode: .common) + } + } + + private func timerStop() { + timer.invalidate() + } + + func changeToLabelState(tellerType: TypeOfWork,data: Int){ + DispatchQueue.main.sync { [self] in + for label in bankView.readyListStackView.arrangedSubviews { + if label.tag == data { + bankView.readyListStackView.removeArrangedSubview(label) + bankView.runningListStackView.addArrangedSubview(label) + break + } + } + } + } + + func removeLabel(data: Int) { + DispatchQueue.main.sync { [self] in + for label in bankView.runningListStackView.arrangedSubviews { + if label.tag == data { + label.removeFromSuperview() + break + } + } + if bankView.runningListStackView.arrangedSubviews.isEmpty && bankView.readyListStackView.arrangedSubviews.isEmpty { + timerStop() + } + } + } + + func addTaskLabel(type: TypeOfWork, number: Int, textColor: UIColor){ + DispatchQueue.main.async { [self] in + let label = bankView.configureTaskLabel(type: type, number: number, textColor: textColor) + bankView.readyListStackView.addArrangedSubview(label) + } + } + + private func configureBankView() { + let safeArea = view.safeAreaLayoutGuide + + bankView.translatesAutoresizingMaskIntoConstraints = false + + bankView.topAnchor.constraint(equalTo: safeArea.topAnchor).isActive = true + bankView.bottomAnchor.constraint(equalTo: safeArea.bottomAnchor).isActive = true + bankView.leadingAnchor.constraint(equalTo: safeArea.leadingAnchor).isActive = true + bankView.trailingAnchor.constraint(equalTo: safeArea.trailingAnchor).isActive = true + + bankView.configure() + bankView.setupAutoLayout() + + bankView.addCustomerButton.addTarget(self, action: #selector(addCustomer), for: .touchUpInside) + bankView.resetButton.addTarget(self, action: #selector(reset), for: .touchUpInside) + } +} - +extension ViewController { + + @objc private func setTimerLabel() { + let minute = String(format: "%02d", Int(time) / 60) + let second = String(format: "%02d", Int(time) % 60) + let millisecond = String(format: "%03d" , Int(time * 1000) % 1000) + + time += 0.001 + + bankView.timerTitleLabel.text = "\(minute) : \(second) : \(millisecond)" + } + + @objc private func addCustomer() { + bankManager.createCustomerQueue() + + startTimer() + bankManager.startTask() + } + + @objc private func reset() { + let _ = bankView.readyListStackView.arrangedSubviews.map { $0.removeFromSuperview()} + let _ = bankView.runningListStackView.arrangedSubviews.map { $0.removeFromSuperview()} + bankManager.reset() + timerStop() + time = 0 + bankView.timerTitleLabel.text = "00 : 00 : 000" + } }