ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Android] Text 키오스크
    안드로이드 2024. 3. 15. 16:08

    ✏️ TIL(Today I Learned)

    Kotlin 문법 강의를 들으면서 만들었던 TextRpgGame의 연장선으로 이번에는 Text 키오스크를 만들었다. 

     

    보유 금액을 입력하면 메뉴판을 출력하는데, 메뉴 번호를 입력하면 상세한 메뉴판을 보여준다.

    메뉴를 선택하면, 선택한 메뉴를 출력하면서 장바구니에 추가하겠냐는 말을 묻고 확인 번호를 입력 받으면 메뉴 이름과 함께 장바구니에 추가했다고 출력한다.

    // isBasketEmpty: Boolean = true 장바구니가 비어있는 지 확인하는 플래그
    
    fun addBasket(customer: Customer,selectedMenu: Menu) {
        while (true) {
            try {
                println("${selectedMenu.name} | W ${"%.1f".format(selectedMenu.price)} | ${selectedMenu.description}")
                println("위 메뉴를 장바구니에 추가하시겠습니까?")
                println("1. 확인        2. 취소")
    
                when (inputCustomerInfo("selectNumber").toString()) {
                    "1" -> {
                        customer!!.orders.add(selectedMenu)
                        isBasketEmpty=false
                        println("${selectedMenu.name} <- 장바구니에 추가했습니다.")
                        break
                    }
                    "2" -> {
                        break
                    }
                    else -> {
                        println("유효한 번호를 선택해주세요.")
                    }
                }
            } catch (e: Exception) {
                println("숫자를 다시 선택해주세요.")
            }
        }
    }

    장바구니에 메뉴가 담기면 [ ORDER MENU ] 가 보이게 된다. 5를 입력하면 아래와 같이 장바구니를 확인 가능하다.

    그리고 주문을 선택하면 결제 진행중이라는 말과 함께 메인 스레드를 3초간 멈추게 했다. 보유 금액이 충분하여 결제가 되면 결제 완료 시간도 함께 출력한다. 그리고 장바구니가 비워졌기 때문에 다시 첫 주문 메뉴에 선택 가능한 번호가 0~4로 제한된다.

    fun toPay(customer:Customer, amount: Double){
        var pay = Pay.getInstance()
        println("결제 진행 중입니다...")
        Thread.sleep(3000) // 3초 동안 메인 스레드를 멈춤
        val paymentSuccess = pay.payOrder(customer, amount)
        if (paymentSuccess){
            val paymentCompletionTime = getCurrentTime()
            println("결제를 완료했습니다. ($paymentCompletionTime)")
            customer.orders.clear() // 장바구니 비우기
        }
        orderQueue--
    }
    class Pay private constructor() {
        companion object {
            @Volatile private var instance: Pay? = null
    
            fun getInstance(): Pay {
                // 외부에서 요청왔을때 instance가 null인지 검증
                if(instance == null) {
                    // synchronized로 외부 쓰레드의 접근을 막음
                    synchronized(this) {
                        instance = Pay()
                    }
                }
                return instance!!
            }
        }
    
        fun payOrder(customer: Customer, amount: Double): Boolean {
            val paymentSuccess: Boolean
            if (customer.balance >= amount) {
                val remainingMoney = (customer.balance - amount).toBigDecimal().setScale(2, RoundingMode.HALF_UP)
                println("[구매 후 잔액]: [${customer.balance} - ${amount}] = W $remainingMoney")
                customer.balance = remainingMoney.toDouble()
                paymentSuccess = true
            } else {
                val lackingMoney = (amount - customer.balance).toBigDecimal().setScale(2, RoundingMode.HALF_UP)
                println("[현재 보유 금액]: W ${customer.balance}\nW $lackingMoney 만큼 부족해서 주문할 수 없습니다.\n")
                paymentSuccess = false
            }
            return paymentSuccess
        }
    }

     

    처음에 금액을 계산할 떄 부동 소수점 연산문제가 생겨서,
    toBigDecimal().setScale(2, RoundingMode.HALF_UP)를 써서 BigDecimal 객체로 변환한 뒤,

    소수점 이하 2자리까지 표시하고 반올림이 되게 만들었다.

     

    그리고 은행 점검 시간이라면 결제를 할 수 없게 만들고, 주문 대기 인원을 5초마다 출력하게 만들었다.

    그와 동시에 메인 스레드는 주문을 받을 수 있어야하므로 새 스레드를 만들고 그 안에서 출력했다.

    val bankMaintenanceStartTime = LocalTime.of(15, 45) //은행점검 시작시간
    val bankMaintenanceEndTime = LocalTime.of(16, 0) // 은행점검 종료시간
    
    fun displayOrderQueue() {
        thread(start = true) {
            while (isMaintenanceTime()) { // 은행 점검시간이 끝날 때까지
                Thread.sleep(1000) // 잠깐 대기 후 출력
                runBlocking {
                    println("(현재 주문 대기수: $orderQueue)\n")
                    launch {
                        delay(5000)
                    }
                }
            }
        }
    }
    
    fun isMaintenanceTime():Boolean  {
        val currentTime = LocalTime.now()
        return currentTime in bankMaintenanceStartTime..bankMaintenanceEndTime
    }
    
    fun getCurrentTime(): String {
        val formatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
        val currentTime = Date()
        return formatter.format(currentTime)
    }

     

    은행 점검 시간을 판별하기 위해서 LocalTime.of() 메소드를 사용해, 특정 시간 값을 갖는 LocalTime 객체를 만들었다.

    LocalTime of(int hour, int minute, int second, int nanoOfSecond) 매개변수는 이처럼 구성되어 있다.

    이와 .. 연산자를 통해 현재 시간이 은행 점검 시간인지의 여부를 리턴하는 함수를 만들 수 있었다. 

Designed by Tistory.