Skip to content

Commit

Permalink
Merge pull request #119 from leeari95/4-leeari95
Browse files Browse the repository at this point in the history
쥬스메이커 [STEP 2] 제이티, Ari
  • Loading branch information
daheenallwhite authored Nov 2, 2021
2 parents 1c0605d + 494468c commit 5b90c88
Show file tree
Hide file tree
Showing 10 changed files with 386 additions and 84 deletions.
13 changes: 13 additions & 0 deletions JuiceMaker/JuiceMaker.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
objects = {

/* Begin PBXBuildFile section */
6B5FDE8C272A761200C04135 /* Message.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B5FDE8B272A761200C04135 /* Message.swift */; };
6B5FDEAE272ADC7100C04135 /* Text.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B5FDEAD272ADC7100C04135 /* Text.swift */; };
6BEB79292726956400FF66D4 /* FruitStoreViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BEB79282726956400FF66D4 /* FruitStoreViewController.swift */; };
9A757554271D599A00108EB8 /* RequestError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A757553271D599A00108EB8 /* RequestError.swift */; };
C71CD66B266C7ACB0038B9CB /* FruitStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = C71CD66A266C7ACB0038B9CB /* FruitStore.swift */; };
Expand All @@ -20,6 +22,10 @@
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
6B5FDE8B272A761200C04135 /* Message.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Message.swift; sourceTree = "<group>"; };
6B5FDEAD272ADC7100C04135 /* Text.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Text.swift; sourceTree = "<group>"; };
6B5FDEAF272ADD5E00C04135 /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/Main.strings; sourceTree = "<group>"; };
6B5FDEB0272ADD5E00C04135 /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/LaunchScreen.strings; sourceTree = "<group>"; };
6BEB79282726956400FF66D4 /* FruitStoreViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FruitStoreViewController.swift; sourceTree = "<group>"; };
9A757553271D599A00108EB8 /* RequestError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestError.swift; sourceTree = "<group>"; };
C71CD66A266C7ACB0038B9CB /* FruitStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FruitStore.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -62,6 +68,8 @@
C73DAF4B255D0D0400020D38 /* JuiceMaker.swift */,
C71CD66A266C7ACB0038B9CB /* FruitStore.swift */,
9A757553271D599A00108EB8 /* RequestError.swift */,
6B5FDE8B272A761200C04135 /* Message.swift */,
6B5FDEAD272ADC7100C04135 /* Text.swift */,
);
path = Model;
sourceTree = "<group>";
Expand Down Expand Up @@ -144,6 +152,7 @@
knownRegions = (
en,
Base,
ko,
);
mainGroup = C73DAF2A255D0CDC00020D38;
productRefGroup = C73DAF34255D0CDD00020D38 /* Products */;
Expand Down Expand Up @@ -175,7 +184,9 @@
files = (
C71CD66B266C7ACB0038B9CB /* FruitStore.swift in Sources */,
C73DAF3B255D0CDD00020D38 /* JuiceMakerViewController.swift in Sources */,
6B5FDE8C272A761200C04135 /* Message.swift in Sources */,
9A757554271D599A00108EB8 /* RequestError.swift in Sources */,
6B5FDEAE272ADC7100C04135 /* Text.swift in Sources */,
C73DAF37255D0CDD00020D38 /* AppDelegate.swift in Sources */,
C73DAF39255D0CDD00020D38 /* SceneDelegate.swift in Sources */,
C73DAF4C255D0D0400020D38 /* JuiceMaker.swift in Sources */,
Expand All @@ -190,6 +201,7 @@
isa = PBXVariantGroup;
children = (
C73DAF3D255D0CDD00020D38 /* Base */,
6B5FDEAF272ADD5E00C04135 /* ko */,
);
name = Main.storyboard;
sourceTree = "<group>";
Expand All @@ -198,6 +210,7 @@
isa = PBXVariantGroup;
children = (
C73DAF42255D0CDF00020D38 /* Base */,
6B5FDEB0272ADD5E00C04135 /* ko */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
Expand Down
122 changes: 120 additions & 2 deletions JuiceMaker/JuiceMaker/Controller/JuiceMakerViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,129 @@ import UIKit

class JuiceMakerViewController: UIViewController {

private let juiceMaker = JuiceMaker()

@IBOutlet weak var strawberryStockLabel: UILabel!
@IBOutlet weak var bananaStockLabel: UILabel!
@IBOutlet weak var pineappleStockLabel: UILabel!
@IBOutlet weak var kiwiStockLabel: UILabel!
@IBOutlet weak var mangoStockLabel: UILabel!

@IBOutlet weak var orderStrawberryBananaJuiceButton: UIButton!
@IBOutlet weak var orderMangoKiwiJuiceButton: UIButton!
@IBOutlet weak var orderStrawberryJuiceButton: UIButton!
@IBOutlet weak var orderBananaJuiceButton: UIButton!
@IBOutlet weak var orderPineappleJuiceButton: UIButton!
@IBOutlet weak var orderKiwiJuiceButton: UIButton!
@IBOutlet weak var orderMangoJuiceButton: UIButton!

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
updateFruitLabels()

NotificationCenter.default.addObserver(self, selector: #selector(fruitLabelChanged(notification:)), name: .changedFruitStockNotification, object: nil)
}

@IBAction func orderJuiceButtonTapped(_ sender: UIButton) {
let juice: Juice

switch sender {
case orderStrawberryBananaJuiceButton:
juice = .strawberryBanana
case orderMangoKiwiJuiceButton:
juice = .mangoKiwi
case orderStrawberryJuiceButton:
juice = .strawberry
case orderBananaJuiceButton:
juice = .banana
case orderPineappleJuiceButton:
juice = .pineapple
case orderKiwiJuiceButton:
juice = .kiwi
case orderMangoJuiceButton:
juice = .mango
default:
showNotificationAlert(message: Message.unknownError.description)
return
}

mixFruit(juice: juice)
}

func mixFruit(juice: Juice) {
do {
try juiceMaker.mixFruit(juice: juice)
showNotificationAlert(message: Message.juiceFinish(juice: juice).description)
} catch RequestError.fruitStockOut {
showOutOfStockAlert()
} catch let error as RequestError {
showNotificationAlert(message: error.errorDescription)
} catch {
showNotificationAlert(message: Message.unknownError.description)
}
}

@objc func fruitLabelChanged(notification: Notification) {
guard let fruit = notification.object as? Fruit else {
showNotificationAlert(message: Message.unknownError.description)
return
}
currentStockLabelUpdate(fruit: fruit, label: fruitlabel(of: fruit))
}


func updateFruitLabels() {
currentStockLabelUpdate(fruit: .strawberry, label: strawberryStockLabel)
currentStockLabelUpdate(fruit: .banana, label: bananaStockLabel)
currentStockLabelUpdate(fruit: .pineapple, label: pineappleStockLabel)
currentStockLabelUpdate(fruit: .kiwi, label: kiwiStockLabel)
currentStockLabelUpdate(fruit: .mango, label: mangoStockLabel)
}

func currentStockLabelUpdate(fruit: Fruit, label: UILabel) {
do {
let stock = try FruitStore.shared.stock(fruit: fruit)
label.text = stock.description
} catch let error as RequestError {
showNotificationAlert(message: error.errorDescription)
} catch {
showNotificationAlert(message: Message.unknownError.description)
}
}

func fruitlabel(of fruit: Fruit) -> UILabel {
switch fruit {
case .strawberry:
return strawberryStockLabel
case .banana:
return bananaStockLabel
case .pineapple:
return pineappleStockLabel
case .kiwi:
return kiwiStockLabel
case .mango:
return mangoStockLabel
}
}

func showNotificationAlert(message: String, title: String = Text.ok.title) {
let alert = UIAlertController(title: nil, message: message, preferredStyle: .alert)
let cancel = UIAlertAction(title: title, style: .cancel, handler: nil)
alert.addAction(cancel)
present(alert, animated: true, completion: nil)
}

func showOutOfStockAlert() {
let alert = UIAlertController(title: nil, message: Message.outOfStock.description, preferredStyle: .alert)
let cancelAction = UIAlertAction(title: Text.cancel.title, style: .cancel, handler: nil)
let okAction = UIAlertAction(title: Text.ok.title, style: .default, handler: presentFruitStoreViewController)
alert.addAction(cancelAction)
alert.addAction(okAction)
present(alert, animated: true, completion: nil)
}

private func presentFruitStoreViewController(_ action: UIAlertAction) {
guard let viewController = self.storyboard?.instantiateViewController(withIdentifier: "FruitStoreViewController") else { return }
self.present(viewController, animated: true, completion: nil)
}
}

37 changes: 25 additions & 12 deletions JuiceMaker/JuiceMaker/Model/FruitStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,37 @@

import Foundation

private let defaultFruitCount = 10

enum Fruit: CaseIterable {
case strawberry
case banana
case pineapple
case kiwi
case mango
}

private enum Const {
static let defaultFruitCount = 10
}

class FruitStore {

static let shared: FruitStore = FruitStore()

enum Fruit: CaseIterable {
case strawberry
case banana
case pineapple
case kiwi
case mango
}

private var fruitBasket: [Fruit: Int]

init(count: Int = defaultFruitCount) {
init(count: Int = Const.defaultFruitCount) {
let allFruits = Fruit.allCases
let fruitscount = Array(repeating: count, count: allFruits.count)

self.fruitBasket = Dictionary(uniqueKeysWithValues: zip(allFruits, fruitscount))
}

func stock(fruit: Fruit) throws -> Int {
guard let fruitStock = fruitBasket[fruit] else {
throw RequestError.fruitNotFound
}
return fruitStock
}

func addFruitStock(fruit: Fruit, count: Int) throws {
try changeAmount(count: count, of: fruit, by: +)
}
Expand All @@ -49,6 +57,8 @@ class FruitStore {
}
let newFruitCount = calculator(oldFruitCount, count)
fruitBasket[fruit] = newFruitCount

NotificationCenter.default.post(name: .changedFruitStockNotification, object: fruit)
}

func hasFruitStock(of fruit: Fruit, count fruitCountSubtracted: Int) -> Bool {
Expand All @@ -58,3 +68,6 @@ class FruitStore {
}


extension Notification.Name {
static let changedFruitStockNotification = Notification.Name("changeFruitStock")
}
22 changes: 13 additions & 9 deletions JuiceMaker/JuiceMaker/Model/JuiceMaker.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,20 @@

import Foundation

fileprivate typealias Recipe = [FruitStore.Fruit: Int]
fileprivate typealias Recipe = [Fruit: Int]

enum Juice {
case strawberry
case banana
case kiwi
case pineapple
case strawberryBanana
case mango
case mangoKiwi
enum Juice: String {
case strawberry = "딸기"
case banana = "바나나"
case kiwi = "키위"
case pineapple = "파인애플"
case strawberryBanana = "딸바"
case mango = "망고"
case mangoKiwi = "망키"

var name: String {
return rawValue
}

fileprivate var recipe: Recipe {
switch self {
Expand Down
25 changes: 25 additions & 0 deletions JuiceMaker/JuiceMaker/Model/Message.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//
// Text.swift
// JuiceMaker
//
// Created by 김진태 on 2021/10/28.
//

import Foundation

enum Message: CustomStringConvertible {
case juiceFinish(juice: Juice)
case unknownError
case outOfStock

var description: String {
switch self {
case .juiceFinish(let juice):
return "\(juice.name) 쥬스 나왔습니다! 맛있게 드세요!"
case .unknownError:
return "알 수 없는 에러가 발생했습니다."
case .outOfStock:
return "재료가 모자라요. 재고를 수정할까요?"
}
}
}
2 changes: 1 addition & 1 deletion JuiceMaker/JuiceMaker/Model/RequestError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import Foundation

enum RequestError: Error, LocalizedError {
enum RequestError: Error {
case wrongCount
case fruitNotFound
case fruitStockOut
Expand Down
32 changes: 32 additions & 0 deletions JuiceMaker/JuiceMaker/Model/Text.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//
// Text.swift
// JuiceMaker
//
// Created by 김진태 on 2021/10/28.
//

import UIKit.UIButton

enum Text {
case cancel
case ok

var title: String {
return localizedTitle(key: self.key)
}

private var key: String {
switch self {
case .cancel:
return "Cancel"
case .ok:
return "OK"
}
}

private func localizedTitle(key: String) -> String {
let bundle = Bundle.init(for: UIButton.self)
let title = bundle.localizedString(forKey: key, value: nil, table: nil)
return title
}
}
Loading

0 comments on commit 5b90c88

Please # to comment.