[Android / Kotlin] 키오스크 프로그램 구현 (4)

Subeen·2023년 12월 14일
0

Kotlin 문법

목록 보기
18/23

이전에 메인 메뉴를 Map을 사용하여 관리했는데 결국 Key와 value를 이용해 index를 활용해 처리하고 있어서 처음부터 List 형태로 구성해도 괜찮겠다는 튜터님의 피드백을 참고하여 List 형태로 관리하고자 메인 메뉴의 속성id, title, explain, category이 포함된 데이터 클래스를 추가로 생성했다.

data class MainMenu(val id:Int, val title: String, val explain: String, val category: String)

MainProduct.kt

  • 데이터 클래스 객체 타입의 ArrayList를 생성하여 데이터를 추가하고 메뉴 선택시 메뉴 타이틀과 목록을 출력해주기 위한 클래스다.
class MainProduct {
    private val mainList = ArrayList<MainMenu>()

    init {
        mainList.add(MainMenu(0, "Burger", "주문 즉시 바로 조리해 더욱 맛있는, 맥도날드의 다양한 버거를 소개합니다.", "McDonald's MENU"))
        mainList.add(MainMenu(1, "Side & Dessert", "버거와 함께 즐기면 언제나 맛있는 사이드와 디저트 메뉴!", "McDonald's MENU"))
        mainList.add(MainMenu(2, "Mac Cafe & Beverage", "언제나 즐겁게, 맥카페와 다양한 음료를 부담없이 즐기세요!", "McDonald's MENU"))
        mainList.add(MainMenu(3, "Order", "장바구니를 확인 후 주문합니다.", "ORDER MENU"))
        mainList.add(MainMenu(4, "Cancel", "진행중인 주문을 취소합니다.", "ORDER MENU"))
    }

    fun displayMain() {
        println("\n아래 메뉴판을 보시고 메뉴를 골라 입력해주세요. \n")

        var category = ""
        for (item in mainList) {
        	// 메뉴별 타이틀을 한 번만 출력하기 위해서 category 변수를 선언하여 아이템의 카테고리 값과 변수 category에 저장 된 값이 다를 경우만 출력한다. 
            if (category != item.category) {
                category = item.category
                println("[${category}]")
            }
            println("%d. %-20s | %s".format(item.id + 1, item.title, item.explain))
        }
    }

    fun displayTitle(index: Int) {
        val item = mainList.find { it.id == index - 1 }
        if (item == null) {
            return
        } else {
            println("[${item.title} MENU]")
        }
    }
}

Bank.kt

사용자에게 랜덤하게 금액을 넣어주고 상품 주문시 현재 잔액과 가격을 비교해서 구매 가능한 상태를 정의하기 위해 Bank 클래스를 추가 생성했다.

  • inBalance(money: Int): Boolean
    • 사용자의 총 금액인 amount에 전달 받은 money를 더해준다.
  • outBalance(money: Int): Boolean
    • 총 금액 amount와 결제 할 금액을 계산 했을 때 0보다 큰 경우에만 성공적으로 결제가 완료 된다.
class Bank {
    private var amount: Int = 0

    init {
        val initAmount = (10000..30000).random()
        inBalance(initAmount)
    }

    private fun inBalance(money: Int): Boolean {
        amount += money
        return true
    }

    fun outBalance(money: Int): Boolean {
        val tempAmount = amount - money
        return if (tempAmount < 0) {
            println("현재 잔액은 ${decimalFormat(amount)}W 으로 ${decimalFormat(money - amount)}W이 부족해서 주문할 수 없습니다.")
            false
        } else {
            amount -= money
            println("결제를 완료했습니다.")
            true
        }
    }
}

Cart.kt

displayCart()에 총 금액이 출력 된 후에 주문 또는 메뉴판을 선택할 수 있는 기능을 추가했다. 중복되는 while 영역을 함수로 만들어 관리해야 할 것 같다 😓

class Cart {
    private val cartList = ArrayList<AbstractMenu>()
    private var total: Int = 0
    fun getTotal(): Int = total

    fun addItem(item: AbstractMenu?) {
        if (item == null) {
            println("선택하신 상품이 존재하지 않습니다. 관리자에게 문의해주세요.")
        } else {
            cartList.add(item)
            total += item.price
        }
    }

    fun checkAddItem(item: AbstractMenu?): Boolean {
        if (item == null) {
            println("선택하신 상품이 존재하지 않습니다. 관리자에게 문의해주세요.")
            return false
        } else {
            println(
                "\"${MenuManager(item).displayInfo()}\"\n" +
                        "위 메뉴를 장바구니에 추가하시겠습니까?\n" +
                        "1. 확인    2. 취소"
            )
            while (true) {
                val input = readln()
                var select: Int
                if (input.isNumber()) {
                    select = input.toInt()
                } else {
                    continue
                }
                return when (select) {
                    1 -> {
                        println("${item.name}이(가) 장바구니에 추가되었습니다.")
                        true
                    }

                    2 -> {
                        false
                    }

                    else -> {
                        println("잘 못 된 번호를 입력했어요. 다시 입력해주세요.")
                        continue
                    }
                }
            }
        }
    }

    fun displayCart(): Boolean {
        if (cartList.isEmpty()) {
            println("장바구니가 비어 있습니다.")
            return false
        } else {
            val listGroup = cartList.groupingBy { it }.eachCount()
            for ((item, count) in listGroup) {
                println("${item.displayInfo()} (${count})")
            }

            println(
                "\n[ Total ]\n" +
                        "₩ ${decimalFormat(total)}"
            )

            println("1. 주문    2. 메뉴판")
            while (true) {
                val input = readln()
                var select: Int
                if (input.isNumber()) {
                    select = input.toInt()
                } else {
                    continue
                }
                return when (select) {
                    1 -> {
                        true
                    }

                    2 -> {
                        false
                    }

                    else -> {
                        println("잘 못 된 번호를 입력했어요. 다시 입력해주세요.")
                        continue
                    }
                }
            }
        }
    }
}

Kiosk.kt

유지보수성, 가독성을 높이기 위해 반복되어 사용되는 값들을 상수로 선언하였다.

const val BURGER = "burger"
const val FRIED = "fried"
const val BEVERAGE = "beverage"

fun main() {
    val productManage = ProductManage()
    val mainProduct = MainProduct()
    val cart = Cart()
    val bank = Bank()

    while (true) {
        mainProduct.displayMain()
        val input = readln()
        var select: Int
        if (input.isNumber()) {
            select = input.toInt()
        } else {
            continue
        }

        mainProduct.displayTitle(select)

        when (select) {
            1 -> {
                productManage.displayMenu(BURGER)

                while (true) {
                    val enter = readln()
                    var number: Int
                    if (enter.isNumber()) {
                        number = enter.toInt()
                    } else {
                        continue
                    }

                    if (number == 0) {
                        break
                    } else if (number < 0 || number > productManage.getMenuCount(BURGER)) {
                        println("잘 못 된 번호를 입력했어요. 다시 입력해주세요.")
                    } else {
                        val item = productManage.getSelectedItem(BURGER, number)
                        if (cart.checkAddItem(item)) {
                            cart.addItem(item)
                        }
                        break
                    }
                }
            }

            2 -> {
                productManage.displayMenu(FRIED)

                while (true) {
                    val enter = readln()
                    var number: Int
                    if (enter.isNumber()) {
                        number = enter.toInt()
                    } else {
                        continue
                    }

                    if (number == 0) {
                        break
                    } else if (number < 0 || number > productManage.getMenuCount(FRIED)) {
                        println("잘 못 된 번호를 입력했어요. 다시 입력해주세요.")
                    } else {
                        val item = productManage.getSelectedItem(FRIED, number)
                        if (cart.checkAddItem(item)) {
                            cart.addItem(item)
                        }
                        break
                    }
                }
            }

            3 -> {
                productManage.displayMenu(BEVERAGE)

                while (true) {
                    val enter = readln()
                    var number: Int
                    if (enter.isNumber()) {
                        number = enter.toInt()
                    } else {
                        continue
                    }

                    if (number == 0) {
                        break
                    } else if (number < 0 || number > productManage.getMenuCount(BEVERAGE)) {
                        println("잘 못 된 번호를 입력했어요. 다시 입력해주세요.")
                    } else {
                        val item = productManage.getSelectedItem(BEVERAGE, number)
                        if (cart.checkAddItem(item)) {
                            cart.addItem(item)
                        }
                        break
                    }
                }
            }

            4 -> {  // Order
                if (cart.displayCart()) {
                    bank.outBalance(cart.getTotal())
                }
            }

            5 -> {
                println("프로그램을 종료합니다.")
                break
            }

            else -> {
                println("잘 못 된 번호를 입력했어요. 다시 입력해주세요.")
            }
        }
    }

}
fun String.isNumber(): Boolean {
    return try {
        this.toInt()
        true
    } catch (e: NumberFormatException) {
        println("잘 못 된 문자 타입을 입력했어요. 다시 입력해 주세요.")
        false
    }
}

가격을 출력할 때 숫자 세 자리마다 쉼표를 붙이기 위해 DecimalFormat 클래스를 사용하여 Format을 변경했다.

fun decimalFormat(price: Int): String {
    val dec = DecimalFormat("#,###")
    return dec.format(price)
}

실행 결과

아래 메뉴판을 보시고 메뉴를 골라 입력해주세요. 

[McDonald's MENU]
1. Burger               | 주문 즉시 바로 조리해 더욱 맛있는, 맥도날드의 다양한 버거를 소개합니다.
2. Side & Dessert       | 버거와 함께 즐기면 언제나 맛있는 사이드와 디저트 메뉴!
3. Mac Cafe & Beverage  | 언제나 즐겁게, 맥카페와 다양한 음료를 부담없이 즐기세요!
[ORDER MENU]
4. Order                | 장바구니를 확인 후 주문합니다.
5. Cancel               | 진행중인 주문을 취소합니다.
1
[Burger MENU]
1. Big Mac    | ₩ 5,500 | 100% 순 쇠고기 패티 두 장에 치즈, 양상추, 피클
2. McCrispy Deluxe Burger | ₩ 6,800 | 100% 통다리살 케이준 치킨 패티, 포테이포 브리오쉬 번
3. McSpicy Shanghai Burger | ₩ 5,500 | 100% 닭가슴살 통살 위에 양상추, 토마토, 치킨 패티
0. 뒤로가기       | 뒤로가기
1
"Big Mac    | ₩ 5,500 | 100% 순 쇠고기 패티 두 장에 치즈, 양상추, 피클"
위 메뉴를 장바구니에 추가하시겠습니까?
1. 확인    2. 취소
1
Big Mac이(가) 장바구니에 추가되었습니다.

아래 메뉴판을 보시고 메뉴를 골라 입력해주세요. 

[McDonald's MENU]
1. Burger               | 주문 즉시 바로 조리해 더욱 맛있는, 맥도날드의 다양한 버거를 소개합니다.
2. Side & Dessert       | 버거와 함께 즐기면 언제나 맛있는 사이드와 디저트 메뉴!
3. Mac Cafe & Beverage  | 언제나 즐겁게, 맥카페와 다양한 음료를 부담없이 즐기세요!
[ORDER MENU]
4. Order                | 장바구니를 확인 후 주문합니다.
5. Cancel               | 진행중인 주문을 취소합니다.
1
[Burger MENU]
1. Big Mac    | ₩ 5,500 | 100% 순 쇠고기 패티 두 장에 치즈, 양상추, 피클
2. McCrispy Deluxe Burger | ₩ 6,800 | 100% 통다리살 케이준 치킨 패티, 포테이포 브리오쉬 번
3. McSpicy Shanghai Burger | ₩ 5,500 | 100% 닭가슴살 통살 위에 양상추, 토마토, 치킨 패티
0. 뒤로가기       | 뒤로가기
1
"Big Mac    | ₩ 5,500 | 100% 순 쇠고기 패티 두 장에 치즈, 양상추, 피클"
위 메뉴를 장바구니에 추가하시겠습니까?
1. 확인    2. 취소
1
Big Mac이(가) 장바구니에 추가되었습니다.

아래 메뉴판을 보시고 메뉴를 골라 입력해주세요. 

[McDonald's MENU]
1. Burger               | 주문 즉시 바로 조리해 더욱 맛있는, 맥도날드의 다양한 버거를 소개합니다.
2. Side & Dessert       | 버거와 함께 즐기면 언제나 맛있는 사이드와 디저트 메뉴!
3. Mac Cafe & Beverage  | 언제나 즐겁게, 맥카페와 다양한 음료를 부담없이 즐기세요!
[ORDER MENU]
4. Order                | 장바구니를 확인 후 주문합니다.
5. Cancel               | 진행중인 주문을 취소합니다.
2
[Side & Dessert MENU]
1. Cheese Sticks - 2조각   | ₩ 2,000 | 자연 모짜렐라 치즈로 빈틈 없이 고소한 치즈스틱
2. Cheese Sticks - 4조각   | ₩ 4,200 | 자연 모짜렐라 치즈로 빈틈 없이 고소한 치즈스틱
3. McNuggets - 4조각   | ₩ 2,600 | 바삭하고 촉촉한 치킨이 한 입에 쏙
4. McNuggets - 6조각   | ₩ 3,800 | 바삭하고 촉촉한 치킨이 한 입에 쏙
0. 뒤로가기       | 뒤로가기
3
"McNuggets - 4조각   | ₩ 2,600 | 바삭하고 촉촉한 치킨이 한 입에 쏙"
위 메뉴를 장바구니에 추가하시겠습니까?
1. 확인    2. 취소
1
McNuggets이(가) 장바구니에 추가되었습니다.

아래 메뉴판을 보시고 메뉴를 골라 입력해주세요. 

[McDonald's MENU]
1. Burger               | 주문 즉시 바로 조리해 더욱 맛있는, 맥도날드의 다양한 버거를 소개합니다.
2. Side & Dessert       | 버거와 함께 즐기면 언제나 맛있는 사이드와 디저트 메뉴!
3. Mac Cafe & Beverage  | 언제나 즐겁게, 맥카페와 다양한 음료를 부담없이 즐기세요!
[ORDER MENU]
4. Order                | 장바구니를 확인 후 주문합니다.
5. Cancel               | 진행중인 주문을 취소합니다.
4
[Order MENU]
Big Mac    | ₩ 5,500 | 100% 순 쇠고기 패티 두 장에 치즈, 양상추, 피클 (2)
McNuggets - 4조각   | ₩ 2,600 | 바삭하고 촉촉한 치킨이 한 입에 쏙 (1)

[ Total ]
₩ 13,600
1. 주문    2. 메뉴판
1
결제를 완료했습니다.
profile
개발 공부 기록 🌱

0개의 댓글