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

Subeen·2023년 12월 20일
0

Kotlin 문법

목록 보기
20/23

키오스크 프로그램의 경우 얼마 전 과제로 나왔던 건데 필수 구현 사항의 레벨이 3단계 까지고 선택 구현 사항의 레벨은 4~7단계까지 있었다. 필수 사항만 구현하여 제출했는데 시간적 여유가 있을 때마다 조금씩 추가 레벨 부분을 구현하고 있다. (현재 5단계를 구현중이다..🐌)
이전에 작성한 코드를 계속 보니 중복 되는 부분이 많아 코드의 재사용성을 높여야 겠다는 생각이 들었다. 그래서 우선적으로 코드를 수정하고 결제시 현재 시간을 비교하여 특정 시간대에는 결제할 수 없다는 알림창을 띄워줘요 부분을 추가로 구현했다.

Bank.kt

class Bank {
    private val now = LocalDateTime.now()  // 현재 시간
    private val start = LocalDateTime.of(now.year, now.month, now.dayOfMonth, 20, 10, 0)  // 은행 점검 시작 시간
    private val end = LocalDateTime.of(now.year, now.month, now.dayOfMonth, 20, 40, 0)  // 은행 점검 종료 시간
    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 (getStatusPayable()) {  // 주문 시간이 은행 점검 시간대일 경우
            println("현재 시각은 ${now.hour}${now.minute}분입니다.")
            println("은행 점검 시간은 ${start.hour}${start.minute}분 ~ ${end.hour}${end.minute}분이므로 결제할 수 없습니다.")
            false
        } else if (tempAmount < 0) {  // 잔액이 부족할 경우
            println("현재 잔액은 ${decimalFormat(amount)}W 으로 ${decimalFormat(money - amount)}W이 부족해서 주문할 수 없습니다.")
            false
        } else {  // 주문 성공
            amount -= money
            println("결제를 완료했습니다.")
            true
        }
    }

    private fun getStatusPayable(): Boolean =  // 주문 시간이 은행 점검 시간대인지 확인
        now.toLocalTime() >= start.toLocalTime() && now.toLocalTime() <= end.toLocalTime()

}

Cart.kt

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 clearItem() {
        cartList.clear()
        total = 0
    }

    fun checkAddItem(item: AbstractMenu?): Boolean {  // 장바구니에 추가 여부를 입력 받기 위한 함수
        return if (item == null) {
            println("선택하신 상품이 존재하지 않습니다. 관리자에게 문의해주세요.")
            false
        } else {
            println(
                "\"${MenuManager(item).displayInfo()}\"\n" +
                        "위 메뉴를 장바구니에 추가하시겠습니까?\n" +
                        "1. 확인    2. 취소"
            )
            getUserConfirm(item)
        }
    }

    private fun getUserConfirm(item: AbstractMenu): Boolean {  // 입력 받는 부분
        while (true) {
            return when (getUserInputAsNumber()) {
                1 -> {
                    println("${item.name}이(가) 장바구니에 추가되었습니다.")
                    true
                }

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

    fun displayCart(): Boolean {  // 장바구니에 담긴 아이템 목록을 출력하는 함수
        return if (cartList.isEmpty()) {
            println("장바구니가 비어 있습니다.")
            false
        } else {
            displayCartItems()
            println(
                "\n[ Total ]\n" +
                        "₩ ${decimalFormat(total)}"
            )
            getUserSelect()
        }
    }

    private fun displayCartItems() {  // 출력 하는 부분
        val listGroup = cartList.groupingBy { it }.eachCount()
        for ((item, count) in listGroup) {
            println("${item.displayInfo()} (${count})")
        }
    }

    private fun getUserSelect(): Boolean {  // 주문 여부를 입력 받기 위한 함수
        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"

val productManager = ProductManager()
val mainProduct = MainProduct()
val cart = Cart()
val bank = Bank()

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

        mainProduct.displayTitle(select)

        when (select) {
            1, 2, 3 -> processMenu(getCategory(select))
            4 -> {
                if (cart.displayCart()) {
                    if (bank.outBalance(cart.getTotal())) { // 주문 성공
                        // TODO 오더 추가
                        cart.clearItem() // 장바구니 리셋
                    }
                }
            }
            5 -> {
                println("프로그램을 종료합니다.")
                break
            }
            else -> {
                println("잘 못 된 번호를 입력했어요. 다시 입력해주세요.")
            }
        }
    }
}

/*
1. 선택한 카테고리별 메뉴 아이템 목록을 출력
2. 추가로 입력 된 번호에 해당되는 아이템을 출력
3. (2) 아이템을 장바구니에 추가 혹은 뒤로가기 
 */
fun processMenu(category: String) {
    productManager.displayMenu(category)

    while (true) {
        val number = getInputNumber()

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

fun getCategory(select: Int): String {  // 입력 된 번호에 해당하는 카테고리를 가져옴 
    return when (select) {
        1 -> BURGER
        2 -> FRIED
        3 -> BEVERAGE
        else -> throw IllegalArgumentException("There are no applicable categories.")
    }
}

fun getInputNumber(): Int {  // 사용자에게 번호를 입력 받기 위한 함수
    while (true) {
        val input = readln()
        if (input.isNumber()) {
            return input.toInt()
        } else {
            println("잘 못 된 번호를 입력했어요. 다시 입력해주세요.")
        }
    }
}

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

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. 뒤로가기       | 뒤로가기
2
"McCrispy Deluxe Burger | ₩ 6,800 | 100% 통다리살 케이준 치킨 패티, 포테이포 브리오쉬 번"
위 메뉴를 장바구니에 추가하시겠습니까?
1. 확인    2. 취소
1
McCrispy Deluxe Burger이(가) 장바구니에 추가되었습니다.

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

[McDonald's MENU]
1. Burger               | 주문 즉시 바로 조리해 더욱 맛있는, 맥도날드의 다양한 버거를 소개합니다.
2. Side & Dessert       | 버거와 함께 즐기면 언제나 맛있는 사이드와 디저트 메뉴!
3. Mac Cafe & Beverage  | 언제나 즐겁게, 맥카페와 다양한 음료를 부담없이 즐기세요!
[ORDER MENU]
4. Order                | 장바구니를 확인 후 주문합니다.
5. Cancel               | 진행중인 주문을 취소합니다.
4
[Order MENU]
McCrispy Deluxe Burger | ₩ 6,800 | 100% 통다리살 케이준 치킨 패티, 포테이포 브리오쉬 번 (1)

[ Total ]
₩ 6,800
1. 주문    2. 메뉴판
1
현재 시각은 20시 38분입니다.
은행 점검 시간은 20시 10분 ~ 20시 40분이므로 결제할 수 없습니다.
profile
개발 공부 기록 🌱

0개의 댓글