Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Step 2 : 우선순위와 다중처리 (리나) #15

Merged
merged 19 commits into from
Jan 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 11 additions & 14 deletions Bank.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,28 @@ import Foundation
final class Bank {
private var clients: [Client] = []
private var tellers: [Teller] = []
private var finishedClientNumber = 0
private var finishedClientCount = 0
private var businessTime: TimeInterval?

func operateBank(teller: Int, client: [Client]) {
let openTime = Date()

initTellers(teller)
clients = client
clients = client.sorted()
assignBusinessToTeller()
businessTime = Date().timeIntervalSince(openTime)
Dashboard.printCloseMessage(finishedClientNumber, businessTime)
Dashboard.printCloseMessage(finishedClientCount, businessTime)
closeBank()
}

private func initTellers(_ number: Int) {
for windowNumber in 1...number {
private func initTellers(_ count: Int) {
for windowNumber in 1...count {
tellers.append(Teller(windowNumber: windowNumber))
}
}

private func assignBusinessToTeller() {
let semaphore = DispatchSemaphore(value: 0)
let dispatchGroup = DispatchGroup()
var isContinue = true

while isContinue {
Expand All @@ -41,20 +41,17 @@ final class Bank {
}
if teller.isNotWorking {
let client = clients.removeFirst()
teller.workingQueue.async {
teller.handleBusiness(for: client)
semaphore.signal()
}
self.finishedClientNumber += 1
teller.handleBusiness(for: client, withDispatchGroup: dispatchGroup)
self.finishedClientCount += 1
}
}
}
for _ in 0..<finishedClientNumber { semaphore.wait() }
dispatchGroup.wait()
}

private func closeBank() {
tellers.removeAll()
clients.removeAll()
finishedClientNumber = 0
finishedClientCount = 0
}
}
46 changes: 44 additions & 2 deletions BankManagerConsoleApp/BankManagerConsoleApp/Client.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,54 @@

import Foundation

final class Client {
struct Clients {
var list: [Client] = []

init(count: Int) {
for waitingNumber in 1...count {
guard let businessType = BusinessType.allCases.randomElement(), let priority = Client.Priority.allCases.randomElement() else {
return
}
list.append(Client(waitingNumber: waitingNumber, businessType: businessType, priority: priority))
}
}
}

struct Client {
enum Priority: Comparable, CaseIterable, CustomStringConvertible {
case VVIP
case VIP
case normal
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

case 이름을 일반으로 하지 않은 이유가 있나요?


var description: String {
switch self {
case .VVIP:
return "VVIP"
case .VIP:
return "VIP"
case .normal:
return "일반"
}
}
}

let waitingNumber: Int
let businessType: BusinessType
let priority: Priority

init(waitingNumber: Int, businessType: BusinessType = .normal) {
init(waitingNumber: Int, businessType: BusinessType = .deposit, priority: Priority = .normal) {
self.waitingNumber = waitingNumber
self.businessType = businessType
self.priority = priority
}
}

extension Client: Comparable {
static func < (lhs: Client, rhs: Client) -> Bool {
return lhs.priority < rhs.priority
}

static func == (lhs: Client, rhs: Client) -> Bool {
return lhs.priority == rhs.priority
}
}
12 changes: 6 additions & 6 deletions BankManagerConsoleApp/BankManagerConsoleApp/Dashboard.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,22 @@

import Foundation

class Dashboard {
struct Dashboard {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

구조체로 바꾼 이유는 무엇인가요?

static func printMenu() {
print(Menu.description, terminator: " ")
}

static func printStatus(for client: Client, about message: Message) {
let message = String(format: message.rawValue, client.waitingNumber)
static func printStatus(for client: Client, about message: String) {
let message = String(format: message, client.waitingNumber, "\(client.priority)", "\(client.businessType)")
print(message)
}

static func printCloseMessage(_ number: Int, _ time: TimeInterval?) {
static func printCloseMessage(_ count: Int, _ time: TimeInterval?) {
guard let time = time else {
print(BankError.unknown.description)
print("\(BankError.unknown)")
return
}
let message = String(format: Message.close.rawValue, number, time)
let message = String(format: Message.close, count, time)
print(message)
}
}
28 changes: 20 additions & 8 deletions BankManagerConsoleApp/BankManagerConsoleApp/Enum.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,36 @@ enum Menu: String {
"""
}

enum Message: String {
case close = "업무가 마감되었습니다. 오늘 업무를 처리한 고객은 총 %d명이며, 총 업무시간은 %.2f초입니다."
case tellerStart = "%d번 고객 업무 시작"
case tellerFinish = "%d번 고객 업무 완료"
enum Message {
static let close = "업무가 마감되었습니다. 오늘 업무를 처리한 고객은 총 %d명이며, 총 업무시간은 %.2f초입니다."
static let tellerStart = "%d번 %@고객 %@업무 시작"
static let tellerFinish = "%d번 %@고객 %@업무 완료"
}
Comment on lines -21 to 25
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

case 을 static let 으로 바꾼 이유는 무엇인가요?


enum BusinessType {
case normal
enum BusinessType: CaseIterable, CustomStringConvertible {
case deposit
case loan

var neededTime: TimeInterval {
switch self {
case .normal:
case .deposit:
return 0.7
case .loan:
return 1.1
}
}

var description: String {
switch self {
case .deposit:
return "예금"
case .loan:
return "대출"
}
}
}

enum BankError: Error {
enum BankError: Error, CustomStringConvertible {
case wrongInput
case unknown

Expand Down
15 changes: 8 additions & 7 deletions BankManagerConsoleApp/BankManagerConsoleApp/Teller.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,14 @@ final class Teller {
workingQueue = DispatchQueue(label: "\(windowNumber)")
}

func handleBusiness(for client: Client) {
let needTimeToWork = client.businessType.neededTime

func handleBusiness(for client: Client, withDispatchGroup group: DispatchGroup) {
isWorking = true
Dashboard.printStatus(for: client, about: .tellerStart)
Thread.sleep(forTimeInterval: needTimeToWork)
Dashboard.printStatus(for: client, about: .tellerFinish)
isWorking = false

workingQueue.async(group: group) {
Dashboard.printStatus(for: client, about: Message.tellerStart)
Thread.sleep(forTimeInterval: client.businessType.neededTime)
Dashboard.printStatus(for: client, about: Message.tellerFinish)
self.isWorking = false
}
}
}
37 changes: 8 additions & 29 deletions BankManagerConsoleApp/BankManagerConsoleApp/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,47 +6,26 @@

import Foundation

private func randomNumber(from minNumber: Int = 0, to maxNumber: Int) -> Int {
return Int.random(in: minNumber...maxNumber)
}

private func initClients(_ number: Int) -> [Client]? {
var clients: [Client] = []

for waitingNumber in 1...number {
clients.append(Client(waitingNumber: waitingNumber))
}
return clients
}

private func main() {
func main() {
let bank = Bank()
let tellerNumber = 3
let maxClientNumber = 30
let minClientNumber = 10
let tellerCount = 3
let maxClientCount = 30
let minClientCount = 10
var isContinue = true

func initClients(_ number: Int) -> [Client] {
var clients: [Client] = []

for waitingNumber in 1...number {
clients.append(Client(waitingNumber: waitingNumber))
}
return clients
}

while isContinue {
Dashboard.printMenu()

guard let input = readLine(), let command = Menu(rawValue: input) else {
print(BankError.wrongInput.description)
print("\(BankError.wrongInput)")
continue
}

switch command {
case .start:
let clients = initClients(randomNumber(from: minClientNumber, to: maxClientNumber))
bank.operateBank(teller: tellerNumber, client: clients)
let randomNumber = Int.random(in: minClientCount...maxClientCount)
let clients = Clients.init(count: randomNumber)
bank.operateBank(teller: tellerCount, client: clients.list)
case .end:
isContinue = false
}
Expand Down