1. 개요
1)클래스
-Menu: 모든 메뉴를 통합해 관리하기위한 추상 클래스
-Pizza: 피자 메뉴를 관리하기 위한 추상클래스, Menu상속
-Drink: 음료 메뉴를 관리하기 위한 추상클래스, Menu상속
-Side: 사이드 메뉴를 관리하기 위한 추상클래스, Menu상속
-CheesePizza
-PepperoniPizza
-PotatoPizza
=> Pizza상속
-Cola
-Beer
-Cider
=>Drink상속
-FrenchFries
-GrilledChicken
=>Side상속
2)main.kt
-초기값 구성
-키오스트 화면 구성
-일부 쓰레드 실행
-기능 구현
3)전체적인 부분
-try-catch로 입력받을때 생기는 예외처리
2. 설명
1)Menu
abstract class Menu() {
abstract var flag:Boolean //메뉴가 주문에 담겨있는지 여부 체크
abstract fun displayInfo() //메뉴 정보 출력
abstract fun orderList() //메뉴 주문 정보 출력
abstract fun order():Int //주문하기
abstract fun changeOrder():Int //담겨있는 주문정보 수정
}
2)Pizza
abstract class Pizza:Menu() {
abstract val name:String
abstract val price:Int
var order=arrayOf(0,0,0) //사이즈 별로 첫번째가 스몰, 두번째가 레귤러, 세번째가 라지
override var flag=false //주문 수량이 없으면 false
override fun displayInfo() {
println("이름: ${name}, 가격: ${price}")
}
override fun orderList() {
if(!flag) return
println("이름: ${name}, 주문수: 스몰-${order[0]} / 레귤러-${order[1]} / 라지-${order[2]}")
}
override fun order():Int {
var sizesTmp:Int?
var num:Int?
while(true){
try {
println("\n[Size]\n")
println("1.스몰\n2.레귤러\n3.라지\n0.메인메뉴로")
sizesTmp= readLine()?.toString()?.toInt()
if(sizesTmp==0) return 0
if(sizesTmp==null||sizesTmp !in 0..3){
println("다시 입력해주세요")
continue
}
println("수량을 입력해 주세요")
num= readLine()?.toString()?.toInt()
if(num==null||num<=0){
println("다시 입력해주세요")
continue
}
}catch (e:Exception){
println("다시 입력해주세요")
continue
}
val tmpSize=when(sizesTmp){
1->"스몰"
2->"레귤러"
else->"라지"
}
println("주문완료: 사이즈-${tmpSize} / 수량-${num}")
flag=true
when(sizesTmp){
1 ->order[0]+=num
2 ->order[1]+=num
else ->order[2]+=num
}
break
}
return num!!*price
}
override fun changeOrder():Int {
var select:Int?
var num:Int?
println("수정을 원하는 사이즈를 입력해주세요\n1.스몰 2.레귤러 3.라지")
while (true){
try {
select= readLine()?.toString()?.toInt()
if(select==null||select !in 1..3){
println("다시 입력해주세요")
continue
}
}catch (e:Exception){
println("다시 입력해주세요")
continue
}
break
}
println("수량을 입력해주세요(정수로 입력)")
while (true){
try {
num= readLine()?.toString()?.toInt()
if(num==null||num+order[select!!-1]<0){
println("다시 입력해주세요")
continue
}
}catch (e:Exception){
println("다시 입력해주세요")
continue
}
break
}
order[select!!-1]+=num as Int
if(order.sum()==0){
flag=false
}
return num* price
}
}
-Menu단계에서 기획했던 의도대로 상속받아 오버라이드 해줌.
-피자의 경우 주문시 사이즈 결정메뉴가 있으므로 그에 맞춰 order를 size 3짜리 배열로 만들고 order()와 changeOrder()에서 사이즈결정 부분을 추가
3)Drink
abstract class Drink:Menu() {
abstract val name:String
abstract val price:Int
var order=arrayOf(0,0) //얼음유무로. 앞이 얼음있는것 뒤가 얼음 없는것
override var flag=false //주문 수량이 없으면 false
override fun displayInfo() {
println("이름: ${name}, 가격: ${price}")
}
override fun orderList() {
if(!flag) return
println("이름: ${name}, 주문수: 얼음 있음-${order[0]} / 얼음 없음-${order[1]}")
}
override fun order():Int {
var ice:Int?
var num:Int?
while(true){
try {
println("얼음을 넣으시겠습니까?\n1.Yes\n2.No\n0.메인메뉴로")
ice= readLine()?.toString()?.toInt()
if(ice==0) return 0
if(ice==null||(ice!=1&&ice!=2)){
println("다시 입력해주세요")
continue
}
println("수량을 입력해 주세요")
num= readLine()?.toString()?.toInt()
if(num==null||num<=0){
println("다시 입력해주세요")
continue
}
}catch (e:Exception){
println("다시 입력해주세요")
continue
}
println("주문완료: 얼음 ${if(ice==1) "넣음" else "안 넣음"} / 수량-${num}")
flag=true
when(ice){
0 ->order[0]+=num
else ->order[1]+=num
}
break
}
return num!!*price
}
override fun changeOrder():Int {
var select:Int?
var num:Int?
println("수정을 원하는 타입을 입력해주세요\n1.얼음 있음 2.얼음 없음")
while (true){
try {
select= readLine()?.toString()?.toInt()
if(select==null||select !in 1..2){
println("다시 입력해주세요")
continue
}
}catch (e:Exception){
println("다시 입력해주세요")
continue
}
break
}
println("수량을 입력해주세요(정수로 입력)")
while (true){
try {
num= readLine()?.toString()?.toInt()
if(num==null||num+order[select!!-1]<0){
println("다시 입력해주세요")
continue
}
}catch (e:Exception){
println("다시 입력해주세요")
continue
}
break
}
order[select!!-1]+=num as Int
if(order.sum()==0){
flag=false
}
return num*price
}
}
-Menu단계에서 기획했던 의도대로 상속받아 오버라이드 해줌.
-Pizza와 유사하게 오버라이드 해주나 음료의 경우 사이즈대신 얼음 유무결정 요소가 있으므로 order를 사이즈2짜리 배열로 만들고 order()와 changeOrder()에서 얼음유무 선택지를 만들어줌
4)Side
abstract class Side:Menu() {
abstract val name:String
abstract val price:Int
var order:Int=0
override var flag=false //주문 수량이 없으면 false
override fun displayInfo() {
println("이름: ${name}, 가격: ${price}")
}
override fun orderList() {
if(!flag) return
println("이름: ${name}, 주문수: ${order}")
}
override fun order():Int {
var num:Int?
while(true){
try {
println("수량을 입력해 주세요(0.메인메뉴로)")
num= readLine()?.toString()?.toInt()
if(num==0) return 0
if(num==null||num<=0){
println("다시 입력해주세요")
continue
}
}catch (e:Exception){
println("다시 입력해주세요")
continue
}
println("주문완료: 수량-${num}")
order+=num
flag=true
break
}
return num!!*price
}
override fun changeOrder():Int {
var select:Int?
var num:Int?
println("수량을 입력해주세요(정수로 입력)")
while (true){
try {
num= readLine()?.toString()?.toInt()
if(num==null||num+order<0){
println("다시 입력해주세요")
continue
}
}catch (e:Exception){
println("다시 입력해주세요")
continue
}
break
}
order+=num as Int
if(order==0){
flag=false
}
return num*price
}
}
-Menu단계에서 기획했던 의도대로 상속받아 오버라이드 해줌.
-Side의 경우 추가 결정 요소가 없으므로 order()와 changeOrder()에서 수량만 받게 함.
5)나머지 클래스: 각각이 상속받은 클래스에 대해 이름과 가격만 오버라이드해주도록 함.
6)main.kt
<1>fun init(menu:ArrayList<Menu>)
fun init(menu:ArrayList<Menu>){
menu+=Cola()
menu+=Cider()
menu+=Beer()
menu+=FrenchFries()
menu+=GrilledChicken()
menu+=CheesePizza()
menu+=PepperoniPizza()
menu+=PotatoPizza()
}
-메뉴들의 초기값을 설정해 리스트에 담아두는 함수
-시작하거나 장바구니에 담은 메뉴를 모두 없애거나 결제시 실행
<2>fun orderMenu(menu: ArrayList<Menu>, category: Int, total:Array<Int>)
fun orderMenu(menu: ArrayList<Menu>, category: Int, total:Array<Int>){
if(category==4){
return chageOrder(menu,total)
}
val tmpMenu=ArrayList<Menu>()
for(i in menu){
if(category==1){
if(i is Pizza){
tmpMenu+=i
}
}else if(category==2){
if(i is Drink){
tmpMenu+=i
}
}else if(category==3){
if(i is Side){
tmpMenu+=i
}
}
}
val title=when(category){
1->"[Pizza]"
2->"[Drink]"
else->"[Side]"
}
println("\n${title}\n")
for(i in tmpMenu.indices) {
print("${i+1}." )
tmpMenu[i].displayInfo()
}
println("0.뒤로가기")
var orders:Int?
while (true){
try{
orders= readLine()?.toString()?.toInt()
if(orders!=null&&orders==0) return
if(orders==null||orders !in 1..tmpMenu.size){
println("다시 입력해주세요")
continue
}
}catch (e:Exception){
println("다시 입력해주세요")
continue
}
break
}
total[0]+=tmpMenu[orders!!-1].order()
}
-세부메뉴를 보여주는 함수. 메뉴선택시 클래스에 있는 함수인 order()함수를 실행하며 총 주문 금액을 올려준다.
<3>fun chageOrder(menu: ArrayList<Menu>,total: Array<Int>)
fun chageOrder(menu: ArrayList<Menu>,total: Array<Int>){
if(!checkOrder(menu,total,true)) return
println("수정을 원하는 메뉴를 선택해주세요")
var select:Int?
var size=menu.filter{it.flag==true}.size
while (true){
try {
select= readLine()?.toString()?.toInt()
if(select!=null&&select==0) return
if(select==null||select !in -1..size){
println("다시 입력해주세요")
continue
}
}catch (e:Exception){
println("다시 입력해주세요")
continue
}
break
}
if(select==-1){
menu.clear()
init(menu)
total[0]=0
}else{
for(i in menu){
if(i.flag){
size--
}
if(size==0){
total[0]+=i.changeOrder()
break
}
}
}
}
-주문 확인 및 수정을 원할시 실행되는 함수
-담아둔 주문의 목록을 보여주고 선택시 클래스에 포함된 changeOrder()함수를 실행한다.
-이후 총 주문 금액 변경
<4>fun checkOrder(menu: ArrayList<Menu>,total: Array<Int>,flags:Boolean):Boolean
fun checkOrder(menu: ArrayList<Menu>,total: Array<Int>,flags:Boolean):Boolean{
//주문이 하나도 없으면 종료
var flag=false
for(i in menu){
if(i.flag) flag=true
}
if(!flag){
println("아직 담은 메뉴가 없습니다.\n")
return flag
}
println("\n[Order]")
var idx=1
for(i in menu.indices){
if(menu[i].flag) print("${idx++}.")
menu[i].orderList()
}
if(flags){
println("0.뒤로가기\n-1.전체 삭제")
}
println("\n[Total]\n${total[0]} 원")
return flag
}
-담아둔 주문 목록을 보여주는 함수
-주문 정보 확인 및 수정하거나 결제시 실행된다.
<5>fun main()
fun main(){
val menu=ArrayList<Menu>()
init(menu)
var money:Int?
val total= arrayOf<Int>(0)
//결제시 주문 대기수 올라감
var waiting=0
while (true){
println("현재 소지한 금액을 입력해주십시오")
try {
money= readLine()?.toString()?.toInt()
if(money==null||money<0){
println("다시 입력해주세요")
continue
}
}catch (e:Exception){
println("다시 입력해주세요")
continue
}
break
}
//주문 대기수
//결제시 주문대기자 수 증가
var endFlag=true
val wait=thread(start=true){
try {
Thread.sleep(5000)
}catch (e:Exception){
}
while (endFlag){
try {
println("현재 주문 대기수:${waiting}")
Thread.sleep(5000)
}catch (e:Exception){
}
}
println("종료되었습니다")
}
while (true){
println("\n로딩중...")
try {
Thread.sleep(3000)
}catch (e:Exception){}
println()
var category:Int?
try {
println("\n[MENU]\n")
println("1.피자\n2.음료\n3.사이드\n4.주문확인 및 수정\n5.결제\n0.종료")
category= readLine()?.toString()?.toInt()
if(category!=null&&category==0) break
if(category==null||(category!=0&&category !in 1..5)) {
println("다시 입력해주세요")
continue
}
}catch (e: Exception){
println("다시 입력해주세요")
continue
}
if(category==5){
if(total[0]==0){
println("아직 주문하지 않았습니다. 메뉴를 담은 후에 결제해주세요")
}else{
checkOrder(menu,total,false)
println("결제하시겠습니까?\n1.Yes 2.No")
var choose:Int?
while (true){
try {
choose= readLine()?.toString()?.toInt()
if(choose==null||choose !in 1..2){
println("다시 입력해주세요")
continue
}
}catch (e: Exception){
println("다시 입력해주세요")
continue
}
break
}
if(choose==1){
val time=LocalDateTime.now()
val form=DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
val formtime=DateTimeFormatter.ofPattern("HHmm")
val curtime=time.format(formtime).toInt()
if(curtime in 2000..2100){
println("현재시간은 ${curtime/100}시 ${curtime%100}분입니다.")
println("은행 점검 시간은 20시 00분 ~ 21시:00이므로 결제할 수 없습니다.")
continue
}
if(money!!<total[0]){
println("현재 잔액은 ${money}원으로 ${total[0]-money}원이 부족합니다")
continue
}
money = money!!.minus(total[0])
total[0]=0
menu.clear()
init(menu)
println("결제가 완료되었습니다(${time.format(form)})")
println("남은 금액: ${money}원")
++waiting
}else{
println("결제가 취소되었습니다")
}
}
}else{
orderMenu(menu,category,total)
}
}
endFlag=false
}
-wait쓰레드로 주문대기수 지속적으로 출력:endFlag를 이용해 종료시 같이 종료되도록 함.
-while문을 이용해 특정 작업종료이후에도 메인메뉴를 보여주는것을 반복시키도록 함
-위의 while문 내에 Thread.sleep()을 이용해 특정작업종료 후 대기시간이 있도록 만들음
-메인 메뉴에 피자, 음료,사이드,주문 확인 및 수정, 결제, 종료를 넣고 선택이 그에 맞는 함수를 실행.
-결제의 경우 메인메뉴의 while문에서 처리
-LocalDateTime을 이용해 결제시 주문이 안되는 시간을 설정해 놓고 결제완료시 해당 시간을 출력하도록 함
3. 느낀점
-입력받는 값에 대한 예외처리가 번거로웠던 느낌이다. 다음부터는 입력 받는것에 대해 함수를 짜서 해봐야겠다
'코틀린 개인 과제' 카테고리의 다른 글
회원가입 MVVM 과제 (0) | 2024.07.14 |
---|---|
챌린지반 3주차 첫번째 과제: 디자인 패턴 구현 (0) | 2024.07.09 |
로그인 앱 제작-2 (0) | 2024.06.25 |
로그인 앱 제작 (0) | 2024.06.19 |
수식입력이 가능한 계산기 만들기 (0) | 2024.06.04 |