Notice
Recent Posts
Recent Comments
Link
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

Skipalong's tistory

231019 TIL - Kiosk 본문

TIL

231019 TIL - Kiosk

Skipalong 2023. 10. 19. 23:01

예전에 일기처럼 TIL을 써와서 TIL강의를 듣고 그날그날 배운 강의내용을 정리하는 식으로 쓰려고 했는데 TIL강의를 듣자마자 개인과제를 하게 되어서 블로그에 올리는 첫 TIL이 개인과제 내용이다.

 

개인과제 주제는 JAVA로 객체지향을 활용해 키오스크프로그램 만들기 이다.

구글링을 하며 많이 참고하긴 했지만 첫 개인과제를 완성했고 아직까지는 큰 오류 없이 작동하는 것 같다.

자바 문법 강의를 이제 한 번 수강하자마자 바로 배운것을 활용하는것은 힘들었지만 원래 강의자료만 쳐다보고있는것보단 역시 맨땅에 헤딩하는게 효과가 좋은 것 같다. 처음엔 막막했지만 결국 완성은 했으니깐...

 

Main.java

public class Main {
    public static void main(String[] args) throws InterruptedException {
        KioskApp app = new KioskApp();

        app.loadMenu();
        app.start();

    }
}

우선 메인 클래스인데 별 거 없다. 메뉴정보를 저장하고 키오스크앱을 시작하는 것이다.

 

Menu.java

public class Menu {
    private String menuName;
    private String description;

    public Menu(String menuName, String description) {
        this.menuName = menuName;
        this.description = description;
    }
    public void information() {
        System.out.printf("%-15s | %s\n ", menuName, description); //상위 메뉴판 출력
    }

    public String getMenuName() {
        return menuName;
    }

    public String getDescription() {
        return description;
    }

}

 

다음은 메뉴 클래스인데 메뉴 이름과 설명을 받는 생성자, 메뉴판에 나타낼 정보를 출력해주는 메서드를 만들어두었다.

 

Product.java

import java.util.Objects;

public class Product extends Menu {
    private double price;
    private String category;
    private double optionPrice;

    public Product(String menuName, String description, double price, String category) {
        super(menuName, description);
        this.price = price;
        this.category = category;
    }
    public Product(String menuName, String description, double price, String category, double optionPrice) {
        super(menuName, description);
        this.price = price;
        this.category = category;
        this.optionPrice = optionPrice;
    }
    public double getPrice() {
        return price;
    }
    public String getCategory() {
        return category;
    }
    public double getOptionPrice() {
        return optionPrice;
    }
    @Override
    public void information() { //상세메뉴 출력
        System.out.printf("%-20s | W %s | %s\n ", getMenuName(), price, getDescription());
    }
    public void information(int cnt) { //장바구니에 담겨있는 상품 출력
        System.out.printf("%-20s | W %s | %s 개 | %s\n ", getMenuName(), price, cnt, getDescription());
    }
    @Override // 옵션선택하는 메뉴 수량 세기위해...
    public boolean equals(Object obj) {
        if (obj instanceof Product) {
            Product temp = (Product) obj;
            return this.getMenuName().equals(temp.getMenuName()) &&
                    this.getPrice() == temp.getPrice() &&
                    this.getOptionPrice() == temp.getOptionPrice() &&
                    this.getDescription().equals(temp.getDescription()) &&
                    this.getCategory().equals(temp.getCategory());
        }
        return false;
    }
    public int hashCode() {
        return Objects.hash(getMenuName(), getDescription(), getPrice(), getOptionPrice(), getCategory());
    }
}

 

여기부터 머리가 안굴러갔다... 과제 조건인 Menu를 상속받아 메뉴이름과 간단설명을 super()로 부모 생성자를 호출하는것까진 강의자료를 보며 적었지만 이 안에 어떤 변수와 메서드들을 넣어야할지 감이 오질 않았다. 그래서 구글링을해서  큰 틀을 참고하였고 get메서드만 간단히 적고 나머지는 나중에 추가하기로했다.

 

KioskApp.java

import java.util.*;

public class KioskApp {
    private Order order = new Order();
    private List<Menu> categoryMenu = new ArrayList<>(); //상위 메뉴
    private List<Product> allProduct = new ArrayList<>(); // 모든 상품
    private List<Product> categoryProduct = new ArrayList<>(); //카테고리별 상품List


    public void start() throws InterruptedException {
        while (true) {
            shopping();
        }
    }

    public void shopping() throws InterruptedException {
//        메인 메뉴판 시작
        int idx = 1;
        int input;
        Scanner sc = new Scanner(System.in);
        System.out.println("\"SHAKESHACK BURGER 에 오신 걸 환영합니다.\"");
        System.out.println("아래 메뉴판을 보시고 메뉴를 골라 입력해주세요.");
        System.out.println("[ SHAKESHACK MENU ]");
        for (Menu m : categoryMenu) {
            System.out.print(idx + ". ");
            m.information();
            idx++;
        }
        System.out.println("[ ORDER MENU ]");
        System.out.printf(idx + ". %-15s | %s\n", "Order", "장바구니를 확인 후 주문을 완료합니다.");
        idx++;
        System.out.printf(idx + ". %-15s | %s\n", "Cancel", "진행중인 주문을 취소합니다.");
        input = sc.nextInt();

        if (0 < input && input <= idx - 2) {
//            상세 메뉴판 시작
            int categoryIdx = 1;
            categoryProduct.clear();
            System.out.println("\"SHAKESHACK BURGER 에 오신걸 환영합니다.\"");
            System.out.println("아래 상품메뉴판을 보시고 상품을 골라 입력해주세요.");
            String selectedCategory = categoryMenu.get(input - 1).getMenuName();
            System.out.println("[ " + selectedCategory + " MENU ]");
            for (Product p : allProduct) {
                if (selectedCategory.equals(p.getCategory())) {
                    categoryProduct.add(p);
                    System.out.print(categoryIdx + ". ");
                    p.information();
                    categoryIdx++;
                }
            }
            int select = sc.nextInt();
            if (0 < select && select < categoryIdx) {
                order.addShoppingBag(categoryProduct.get(select - 1)); //장바구니 담기
            } else {
                wrongInput();
            }

        } else if (input == idx - 1) {
//            주문 시작
            order.startOrder();

        } else if (input == idx) {
//            캔슬 기능 시작
            order.cancelOrder();

//        히든 기능
        } else if (input == 0) {
            double totalIncome = Math.round(order.getIncome() * 100) / 100.0;
            if (order.getIncome() != 0) {
                System.out.println("[ 총 판매 금액 현황 ]");
                System.out.println("현재까지 총 판매된 금액은 [ W " + totalIncome + " ] 입니다.\n");

                System.out.println("[ 총 판매상품 목록 현황 ]");
                System.out.println("현재까지 총 판매된 상품 목록은 아래와 같습니다.");
                for (Product hs : order.getSoldList()) {
                    System.out.printf("- %-20s | W %s\n", hs.getMenuName(), hs.getPrice());
                }
                System.out.println("\n1. 돌아가기 ");

                int goBack = sc.nextInt();
                if (goBack == 1) {
                    System.out.println("메인 화면으로 돌아갑니다.");
                    countDown();
                } else {
                    wrongInput();
                }

            } else {
                System.out.println("판매 내역이 없습니다.");
                System.out.println("메인 화면으로 돌아갑니다.");
                countDown();
            }

        } else {
            wrongInput();
        }
    }

    public static void countDown() throws InterruptedException { //카운트 다운
        System.out.println("3");
        Thread.sleep(1000);
        System.out.println("2");
        Thread.sleep(1000);
        System.out.println("1");
        Thread.sleep(1000);
    }

    public static void wrongInput() throws InterruptedException { //범위 밖 입력
        System.out.println("잘못된 입력입니다.");
        System.out.println("메인 화면으로 돌아갑니다.");
        countDown();
    }

    public void loadMenu() { //메뉴 정보 저장
        Menu[] menu = {
                new Menu("Burgers", "앵거스 비프 통살을 다져 만든 포테이토 번 버거"),
                new Menu("Frozen Custard", "매장에서 신선하게 만드는 부드럽고 쫀득한 아이스크림"),
                new Menu("Drinks", "매장에서 직접 만드는 상큼한 음료"),
                new Menu("Beer", "뉴욕 브루클린 브루어리에서 양조한 에일 맥주")
        };
        Product[] products = {
                new Product("ShackBurger", "토마토, 양상추, 쉑소스가 토핑된 치즈버거", 6.9, "Burgers", 10.9),
                new Product("SmokeShack", "베이컨, 체리 페퍼에 쉑소스가 토핑된 치즈버거", 8.9, "Burgers", 12.9),
                new Product("'Shroom Burger", "몬스터 치즈와 체다 치즈와 버섯패티를 넣은 베지테리안 버거", 9.4, "Burgers"),
                new Product("Cheeseburger", "포테이토 번과 비프패티, 치즈가 토핑된 치즈버거", 6.9, "Burgers", 10.9),
                new Product("Hamburger", "비프패티를 기본으로 취향따라 토핑을 선택하는 버거", 5.4, "Burgers", 9.0),


                new Product("Shakes", "바닐라, 초콜렛, 솔티드 카라멜, 블랙 & 화이트, 스트로베리, 피넛 버터, 커피", 5.9, "Frozen Custard"),
                new Product("Shake of the Week", "특별한 커스터드 플레이버", 6.5, "Frozen Custard"),
                new Product("Red Bean Shake", "신선한 커스터드와 함께 우유와 레드빈이 블렌딩 된 시즈널 쉐이크", 6.5, "Frozen Custard"),
                new Product("Floats", "루트 비어, 퍼플 카우, 크림 시클", 5.9, "Frozen Custard"),
                new Product("Cups & Cones", "바닐라, 초콜렛, Flavor of the Week", 4.9, "Frozen Custard", 5.9),
                new Product("Concretes", "쉐이크쉑의 쫀득한 커스터드와 다양한 믹스-인의 조합", 5.9, "Frozen Custard", 8.9),
                new Product("Shack Attack", "초콜렛 퍼지소스, 초콜렛 트러플 쿠키, Lumiere 초콜렛 청크와 스프링클이 들어간 진한 초콜렛 커스터드", 5.9, "Frozen Custard"),


                new Product("Shack-made Lemonade", "매장에서 직접 만드는 상큼한 레몬에이드(오리지날/시즈널)", 3.9, "Drinks", 4.5),
                new Product("Fresh Brewed Iced Tea", "직접 유기농 홍차를 우려낸 아이스티", 3.4, "Drinks", 3.9),
                new Product("Fifty/Fifty", "레몬에이드와 아이스티의 만남", 3.5, "Drinks", 4.4),
                new Product("Fountain Soda", "코카콜라, 코카콜라 제로, 스프라이트, 환타 오렌지, 환타 그레이프", 2.7, "Drinks", 3.3),
                new Product("Abita Root Beer", "청량감 있는 독특한 미국식 무알콜 탄산음료", 4.4, "Drinks"),
                new Product("Bottled Water", "지리산 암반대수층으로 만든 프리미엄 생수", 1.0, "Drinks"),


                new Product("ShackMeister Ale", "쉐이크쉑 버거를 위해 뉴욕 브루클린 브루어리에서 특별히 양조한 에일 맥주", 9.8, "Beer"),
                new Product("Magpie Brewing Co.", "Magpie Brewing Co.", 6.8, "Beer"),
        };
        categoryMenu.addAll(Arrays.asList(menu));
        allProduct.addAll(Arrays.asList(products));
    }
}

 

엄청 길다. 우선은 강의때 배운 객체배열을 통해 상품정보를 담았고 그것을 상위메뉴와 모든상품으로 나누어서 arrayList에 저장하였다. 그리고 위에있으면 보기 싫으니 밑으로 내렸다.

내 생각엔 기술적으로 특별한 건 없는것 같지만 이 클래스를 작성하면서 프로그램을 만드는데 도움이 많이 되었다.

일단 첫 화면부터 시작해서 필수로 구현해야하는 기능들을 일단 한글로 쭉 쓰고 그것을 다른클래스들을 최대한 이용하지 않으며 뼈대를 작성 하였다. 그리고 메인메뉴에 1~4번 을 눌렀을때(카테고리별 메뉴), 5번눌렀을 때(order기능),6번눌렀을 때(cancel기능) 부터 구현해야하는 기능들을 붙이다 보니 코드는 더럽지만 굴러가기는 하게 되었다. 그리고 거기서 주문과 관련된 기능들은 Order클래스에, 상품정보가 필요한 정보는 Product클래스에 하나씩 옮기고 반복되는 부분을 메서드화 하면서 프로그램을 완성해나갔다.

 

Order.java

import java.util.*;

public class Order {
    private List<Product> orderList = new ArrayList<>(); //장바구니
    private HashSet<Product> soldList = new HashSet<>(); //판매목록
    int cnt = 0; //주문 순서(대기번호)
    private double income; // 총 수입

    public void addShoppingBag(Product product) throws InterruptedException { //장바구니 담기
        Scanner sc = new Scanner(System.in);
//        옵션가격이 있는 경우
        if (product.getOptionPrice() != 0) {
            product.information();
            Product sizeUpProduct = new Product(product.getMenuName() + "(double)", product.getDescription(), product.getOptionPrice(), product.getCategory(), product.getOptionPrice());
            System.out.println("위 메뉴의 어떤 옵션으로 추가하시겠습니까?");
            System.out.println("1. Single(W " + product.getPrice() + ")          2. Double(W " + sizeUpProduct.getPrice() + ")");
            int optionInput = sc.nextInt();
            if (optionInput == 1) { //기본 옵션 선택
                product.information();
                addQuestion();

                int input = sc.nextInt();
                if (input == 1) {
                    orderList.add(product);
                    System.out.println(product.getMenuName() + " 가 장바구니에 추가되었습니다.");
                } else if (input == 2) {
                    System.out.println("장바구니에 추가하지 않았습니다.");
                } else {
                    KioskApp.wrongInput();
                }

            } else if (optionInput == 2) { //추가 옵션 선택
                sizeUpProduct.information();
                addQuestion();

                int input = sc.nextInt();
                if (input == 1) {
                    orderList.add(sizeUpProduct);
                    System.out.println(sizeUpProduct.getMenuName() + " 가 장바구니에 추가되었습니다.");
                } else if (input == 2) {
                    System.out.println("장바구니에 추가하지 않았습니다.");
                } else {
                    KioskApp.wrongInput();
                }
            } else {
                KioskApp.wrongInput();
            }

        } else { //옵션 가격이 없는 경우
            product.information();
            addQuestion();

            int input = sc.nextInt();
            if (input == 1) {
                orderList.add(product);
                System.out.println(product.getMenuName() + " 가 장바구니에 추가되었습니다.");
            } else if (input == 2) {
                System.out.println("장바구니에 추가하지 않았습니다.");
            } else {
                KioskApp.wrongInput();
            }
        }
    }

    public void startOrder() throws InterruptedException { //주문 시작
        if (!orderList.isEmpty()) {
            Scanner sc = new Scanner(System.in);
            int confirmOrder;
            int EA;
            double totalprice = 0;
            System.out.println("아래와 같이 주문하시겠습니까?");
            System.out.println("[ Orders ]");
            HashSet<Product> orderListSet = new HashSet<>(orderList);
            for (Product p : orderListSet) {
                EA = Collections.frequency(orderList, p);
                p.information(EA);
                totalprice += p.getPrice() * EA;
            }
            totalprice = Math.round((totalprice * 100)) / 100.0;
            System.out.println("[ Total ]");
            System.out.println("W " + totalprice + "\n");
            System.out.println("1. 주문     2. 메뉴판");

            confirmOrder = sc.nextInt();
            if (confirmOrder == 1) {
                income += totalprice;
                soldList.addAll(orderList);
                completeOrder(); //주문완료 및 대기표 발급
            } else if (confirmOrder == 2) {
                System.out.println("주문이 완료되지 않았습니다.");
                System.out.println("(초기 메뉴판으로 돌아갑니다.)");
                KioskApp.countDown();
            } else {
                KioskApp.wrongInput();
            }

        } else {
            blankOrderList(); //장바구니가 비었습니다.
        }
    }
    public void completeOrder() throws InterruptedException { //주문완료 및 대기표 발급
        orderList.clear();
        cnt++;
        System.out.println("주문이 완료되었습니다!");
        System.out.println("대기번호는 [ " + cnt + " ] 번 입니다.");
        System.out.println("(3초후 메뉴판으로 돌아갑니다.)");
        KioskApp.countDown();
    }
    public void cancelOrder() throws InterruptedException { //장바구니 비우기
        Scanner sc = new Scanner(System.in);
        System.out.println("진행하던 주문을 취소하겠습니까?");
        System.out.println("1. 예     2. 아니오");

        int cancelInput = sc.nextInt();
        if (cancelInput == 1) {
            orderList.clear();
            System.out.println("진행하던 주문이 취소되었습니다. 이전 화면으로 돌아갑니다.");
            KioskApp.countDown();
        } else if (cancelInput == 2) {
            System.out.println("주문이 취소되지 않았습니다. 이전 화면으로 돌아갑니다.");
            KioskApp.countDown();
        } else {
            KioskApp.wrongInput();
        }
    }
    public void blankOrderList() throws InterruptedException { //장바구니가 비었습니다.
        System.out.println("주문하신 내용이 없습니다.");
        System.out.println("(초기 메뉴판으로 돌아갑니다.)");
        KioskApp.countDown();
    }
    public void addQuestion() { //장바구니 담기 반복
        System.out.println("위 메뉴를 장바구니에 추가하시겠습니까?");
        System.out.println("1.확인          2.취소");
    }
    public double getIncome() {
        return income;
    }
    public HashSet<Product> getSoldList() {
        return soldList;
    }

}

 

여기도 마찬가지로 엄청 길다. KioskApp클래스에 덕지덕지 코드를 써놓았던 것을 Order클래스에서 많이 가져가서 그런것 같다. 그래도 덕분에 Main클래스는 매우 깔끔했다. 지금은 이렇게 해서 제출을 했는데 튜터님이 코드리뷰를 해주신다고 한다. 이번에 짠 코드는 구글링도 많이 하고 많이 어렵게 느껴졌지만 이걸통해 엉망진창이라도 프로그램을 완성해보았고 피드백을 통해 어떤 방식이 왜 잘못되었고 어떤방향으로 구상을 해 나아가야할지 배울 수 있는 프로젝트가 되었으면 좋겠다.