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] Diana, Gama #363

Open
wants to merge 2 commits into
base: ic_11_diana
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
12 changes: 8 additions & 4 deletions JuiceMaker/JuiceMaker.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,24 @@
objects = {

/* Begin PBXBuildFile section */
06A27C8C2B70F207004B4F10 /* ModifyStockViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06A27C8B2B70F207004B4F10 /* ModifyStockViewController.swift */; };
C71CD66B266C7ACB0038B9CB /* FruitStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = C71CD66A266C7ACB0038B9CB /* FruitStore.swift */; };
C73DAF37255D0CDD00020D38 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C73DAF36255D0CDD00020D38 /* AppDelegate.swift */; };
C73DAF39255D0CDD00020D38 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C73DAF38255D0CDD00020D38 /* SceneDelegate.swift */; };
C73DAF3B255D0CDD00020D38 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C73DAF3A255D0CDD00020D38 /* ViewController.swift */; };
C73DAF3B255D0CDD00020D38 /* JuiceMakerController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C73DAF3A255D0CDD00020D38 /* JuiceMakerController.swift */; };
C73DAF3E255D0CDD00020D38 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C73DAF3C255D0CDD00020D38 /* Main.storyboard */; };
C73DAF40255D0CDE00020D38 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C73DAF3F255D0CDE00020D38 /* Assets.xcassets */; };
C73DAF43255D0CDF00020D38 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C73DAF41255D0CDF00020D38 /* LaunchScreen.storyboard */; };
C73DAF4C255D0D0400020D38 /* JuiceMaker.swift in Sources */ = {isa = PBXBuildFile; fileRef = C73DAF4B255D0D0400020D38 /* JuiceMaker.swift */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
06A27C8B2B70F207004B4F10 /* ModifyStockViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModifyStockViewController.swift; sourceTree = "<group>"; };
C71CD66A266C7ACB0038B9CB /* FruitStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FruitStore.swift; sourceTree = "<group>"; };
C73DAF33255D0CDD00020D38 /* JuiceMaker.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = JuiceMaker.app; sourceTree = BUILT_PRODUCTS_DIR; };
C73DAF36255D0CDD00020D38 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
C73DAF38255D0CDD00020D38 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
C73DAF3A255D0CDD00020D38 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
C73DAF3A255D0CDD00020D38 /* JuiceMakerController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JuiceMakerController.swift; sourceTree = "<group>"; };
C73DAF3D255D0CDD00020D38 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
C73DAF3F255D0CDE00020D38 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
C73DAF42255D0CDF00020D38 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
Expand All @@ -46,7 +48,8 @@
children = (
C73DAF36255D0CDD00020D38 /* AppDelegate.swift */,
C73DAF38255D0CDD00020D38 /* SceneDelegate.swift */,
C73DAF3A255D0CDD00020D38 /* ViewController.swift */,
C73DAF3A255D0CDD00020D38 /* JuiceMakerController.swift */,
06A27C8B2B70F207004B4F10 /* ModifyStockViewController.swift */,
);
path = Controller;
sourceTree = "<group>";
Expand Down Expand Up @@ -167,8 +170,9 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
06A27C8C2B70F207004B4F10 /* ModifyStockViewController.swift in Sources */,
C71CD66B266C7ACB0038B9CB /* FruitStore.swift in Sources */,
C73DAF3B255D0CDD00020D38 /* ViewController.swift in Sources */,
C73DAF3B255D0CDD00020D38 /* JuiceMakerController.swift in Sources */,
C73DAF37255D0CDD00020D38 /* AppDelegate.swift in Sources */,
C73DAF39255D0CDD00020D38 /* SceneDelegate.swift in Sources */,
C73DAF4C255D0D0400020D38 /* JuiceMaker.swift in Sources */,
Expand Down
165 changes: 165 additions & 0 deletions JuiceMaker/JuiceMaker/Controller/JuiceMakerController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
import UIKit

class JuiceMakerController: UIViewController {
@IBOutlet weak var modifyStockButton: UIBarButtonItem!
@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!

private var juiceMaker: JuiceMaker = JuiceMaker()
private var menuList: MenuList = MenuList(strawberryJuice: [JuiceMenu.recipe(.strawberry, 16)],
bananaJuice: [JuiceMenu.recipe(.banana, 3)],
pineappleJuice: [JuiceMenu.recipe(.pineapple, 2)],
kiwiJuice: [JuiceMenu.recipe(.kiwi, 3)],
mangoJuice: [JuiceMenu.recipe(.mango, 3)],
strawberryBananaJuice: [JuiceMenu.recipe(.strawberry, 10), JuiceMenu.recipe(.banana, 1)],
mangoKiwiJuice: [JuiceMenu.recipe(.mango, 2), JuiceMenu.recipe(.kiwi, 1)])

enum AlertType {
case yes
case yesAndNo
}

override func viewDidLoad() {
super.viewDidLoad()

initFruitStockLabel()
}

@IBAction func modifyStockButtonTapped(_ sender: Any) {
moveToModifyStockViewController()
}

@IBAction func orderStrawberryJuice(_ sender: UIButton) {
tryMakingJuice(menu: menuList.strawberryJuice, menuName: "딸기")
}

@IBAction func orderBananaJuice(_ sender: UIButton) {
tryMakingJuice(menu: menuList.bananaJuice, menuName: "바나나")
}

@IBAction func orderStrawberryBananaJuice(_ sender: UIButton) {
tryMakingJuice(menu: menuList.strawberryBananaJuice, menuName: "딸기바나나")
}

@IBAction func orderPineappleJuice(_ sender: UIButton) {
tryMakingJuice(menu: menuList.pineappleJuice, menuName: "파인애플")
}

@IBAction func orderMangoJuice(_ sender: UIButton) {
tryMakingJuice(menu: menuList.mangoJuice, menuName: "망고")
}

@IBAction func orderKiwiJuice(_ sender: UIButton) {
tryMakingJuice(menu: menuList.kiwiJuice, menuName: "키위")
}

@IBAction func orderMangoKiwiJuice(_ sender: UIButton) {
tryMakingJuice(menu: menuList.mangoKiwiJuice, menuName: "망고키위")
}

func initFruitStockLabel() {
for fruit in FruitCategory.allCases {
let fruitCount = String(juiceMaker.manageFruitStore(fruit: fruit))

switch fruit {
case .strawberry:
self.strawberryStockLabel.text = fruitCount
case .banana:
self.bananaStockLabel.text = fruitCount
case .pineapple:
self.pineappleStockLabel.text = fruitCount
case .kiwi:
self.kiwiStockLabel.text = fruitCount
case .mango:
self.mangoStockLabel.text = fruitCount
}
}
}

func tryMakingJuice(menu: [JuiceMenu], menuName: String) {
do {
try juiceMaker.makeJuice(juiceMenu: menu)
tryConsumeFruit(menu: menu, menuName: menuName)
} catch FruitStoreError.outOfStock {
alertMessage(message: "재료가 모자라요. 재고를 수정할까요?", type: .yesAndNo) { _ in
self.moveToModifyStockViewController()
}
} catch FruitStoreError.invalidFruitName {
alertMessage(message: "유효하지 않은 과일 이름입니다.", type: .yes, handler: nil)
} catch {
alertMessage(message: "잘못된 입력입니다.", type: .yes, handler: nil)
}
}

func tryConsumeFruit(menu: [JuiceMenu], menuName: String){
do {
try juiceMaker.consumeFruit(recipe: menu)
alertMessage(message: "\(menuName) 쥬스 나왔습니다! 맛있게 드세요!", type: .yes) { _ in
self.updateMenu(menu: menu)
}
} catch FruitStoreError.invalidFruitName {
alertMessage(message: "유효하지 않은 과일 이름입니다.", type: .yes, handler: nil)
} catch {
alertMessage(message: "잘못된 입력입니다.", type: .yes, handler: nil)
}
}

func updateMenu(menu: [JuiceMenu]) {
for fruit in menu {
switch fruit {
case .recipe(let fruitName, _):
self.updateFruitCount(fruitName: fruitName)
}
}
}

func updateFruitCount(fruitName: FruitCategory) {
let fruitNumberForLabel = String(juiceMaker.manageFruitStore(fruit: fruitName))

switch fruitName {
case .strawberry:
self.strawberryStockLabel.text = fruitNumberForLabel
case .banana:
self.bananaStockLabel.text = fruitNumberForLabel
case .pineapple:
self.pineappleStockLabel.text = fruitNumberForLabel
case .kiwi:
self.kiwiStockLabel.text = fruitNumberForLabel
case .mango:
self.mangoStockLabel.text = fruitNumberForLabel
}
}

func alertMessage(message: String, type: AlertType, handler: ((UIAlertAction) -> Void)?){
let alert = UIAlertController(title: "알림", message: message, preferredStyle: .alert)
var confirm: UIAlertAction = UIAlertAction()
var close: UIAlertAction = UIAlertAction()

switch type {
case .yes:
confirm = UIAlertAction(title: "예", style: .default, handler: handler)

alert.addAction(confirm)
case .yesAndNo:
confirm = UIAlertAction(title: "예", style: .default, handler: handler)
close = UIAlertAction(title: "아니오", style: .destructive, handler: handler)

alert.addAction(confirm)
alert.addAction(close)
}

present(alert, animated: true, completion: nil)
}

func moveToModifyStockViewController(){
guard let viewController = self.storyboard?.instantiateViewController(withIdentifier: "ModifyStockViewController") as? ModifyStockViewController else {
return
}

let navigationController = UINavigationController(rootViewController: viewController)
self.present(navigationController, animated: true)
}
}
13 changes: 13 additions & 0 deletions JuiceMaker/JuiceMaker/Controller/ModifyStockViewController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import UIKit

class ModifyStockViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let closeButton = UIBarButtonItem(title: "닫기", style: .plain, target: self, action: #selector(closeScreen))
self.navigationItem.leftBarButtonItem = closeButton
}

@objc func closeScreen(_ sender: UIButton) {
dismiss(animated: true)
}
}
22 changes: 0 additions & 22 deletions JuiceMaker/JuiceMaker/Controller/ViewController.swift

This file was deleted.

60 changes: 28 additions & 32 deletions JuiceMaker/JuiceMaker/Model/FruitStore.swift
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
//
// JuiceMaker - FruitStore.swift
// Created by yagom.
// Copyright © yagom academy. All rights reserved.
//
enum FruitStoreError: Error {
case outOfStock
case invalidFruitName
}

enum FruitCategory: Int {
enum FruitCategory: Int, CaseIterable {
case strawberry
case banana
case kiwi
Expand All @@ -28,49 +27,46 @@ enum FruitCategory: Int {
}

class FruitStore {
var fruit: [FruitCategory: Int]
private var fruits: [FruitCategory: Int]

init(fruit: [FruitCategory : Int]) {
self.fruit = fruit
init(fruits: [FruitCategory : Int]) {
self.fruits = fruits
}

func checkSufficientStock(recipe: [JuiceMenu]) -> Bool {
for fruitForRecipe in recipe {
return checkFruitStock(fruitForRecipe: fruitForRecipe)
func isAvailable(menu: [JuiceMenu]) throws {
for ingredients in menu {
try isAvailable(fruit: ingredients)
}
return true
}

func checkFruitStock(fruitForRecipe: JuiceMenu) -> Bool {
switch fruitForRecipe {
func isAvailable(fruit: JuiceMenu) throws {
switch fruit {
case .recipe(let fruitName, let number):
guard let fruitNumber = fruit[fruitName] else {
return false
}

if fruitNumber < number {
print("\(fruitName.koreanName)의 재고가 부족합니다.")
return false
if fruits[fruitName] == nil {
throw FruitStoreError.invalidFruitName
} else if fruits[fruitName] ?? 0 < number {
throw FruitStoreError.outOfStock
}
}
return true
}

func consumeStock(recipe: [JuiceMenu]) {
func consumeStock(recipe: [JuiceMenu]) throws {
for fruitForRecipe in recipe {
consumeFruitStock(fruitForRecipe: fruitForRecipe)
try consumeFruitStock(fruitForRecipe: fruitForRecipe)
}
}

func consumeFruitStock(fruitForRecipe: JuiceMenu) {
func consumeFruitStock(fruitForRecipe: JuiceMenu) throws {
switch fruitForRecipe {
case .recipe(let fruitName, let number):
guard var fruitNumber = fruit[fruitName] else {
return
case .recipe(let fruitName, let fruitCountToUse):
guard var fruitCount = fruits[fruitName] else {
throw FruitStoreError.invalidFruitName
}

fruitNumber -= number
fruit[fruitName] = fruitNumber
fruits[fruitName] = fruitCount - fruitCountToUse
}
}

func showFruitStock() -> [FruitCategory: Int] {
return self.fruits
}
}
Loading