Object Oriented Programming | Week 8: ETS coffee vending machine

Dari flow sistem yang diberikan, berikut fitur-fitur utama yang dapat dilakukan pada program vending machine:

1. Order
    1.1 pilih jenis kopi
    1.2 pilih ukuran (small/medium/large)
    1.3 tambahan gula/susu (opsional)
    1.4 tampilkan total harga
    1.5 lakukan pembayaran
2.tambah stock (admin)
3. tampilkan stock (admin)
4. tampilkan log transaksi (admin)

Berikut rancangan class yang saya buat:

Berikut hasil output program yang saya buat (lengkapnya ada di github.com):

Penjelasan implementasi dengan bahasa java:
Class Coffee

/**
 * Write a description of class Coffee here.
 *
 * @author Muhammad Zaky Zein
 * @version 14.10.2025
 */
public class Coffee
{
    private String name;
    private int basePrice;

    public final int SIZE_MEDIUM = 5000;
    public final int SIZE_LARGE = 8000;

    Coffee(String name, int basePrice) {
        this.name = name;
        this.basePrice = basePrice;
    }

    public String getName() { return name; }
    public int getbasePrice() { return basePrice; }
}
Class Coffee hanya berisi nama dari jenis menu kopi, basePrice adalah variable untuk menampung harga dasar dari kopi pada ukuran small, terdapat pula dua variable final (konstan) untuk harga tambahan yang harus dibayarkan untuk size medium dan juga large.


Class Order

/**
 * Write a description of class Order here.
 *
 * @author Muhammad Zaky Zein
 * @version 14.10.2025
 */
public class Order
{
    private Coffee c;
    private boolean extraGula;
    private boolean extraSusu;
    private int size;
    private int extraHarga;
    private int totalHarga;

    public Order(Coffee c, boolean extraGula, boolean extraSusu, int size) {
        this.c = c;
        this.extraGula = extraGula;
        this.extraSusu = extraSusu;
        this.size = size;
        extraHarga = 0;
        setHarga();
    }

    private int hitungTotalHarga() {
        if (extraGula) {
            extraHarga += 500;
        }
        
        if (extraSusu) {
            extraHarga += 2000;
        }

        switch (size) {
            case 1:
                return c.getbasePrice() + extraHarga;
            case 2:
                return c.getbasePrice() + c.SIZE_MEDIUM + extraHarga;
            case 3:
                return c.getbasePrice() + c.SIZE_LARGE + extraHarga;
            default:
                return -1;
        }
    }

    private void setHarga() {
        totalHarga = hitungTotalHarga();
    }

    public String getCoffeeName() { return c.getName(); }
    public boolean getExtraGula() { return extraGula; }
    public boolean getExtraSusu() { return extraSusu; }
    public int getHarga() { return totalHarga; }

    public void printLog() {
        System.out.print("nama: " + getCoffeeName() + " | ");
        if (size == 1) System.out.print("small | "); 
        else if (size == 2) System.out.print("medium | ");
        else if (size == 3) System.out.print("large | ");
        if(extraGula) System.out.print("extra gula | ");
        if(extraSusu) System.out.print("extra susu | ");
        System.out.println("harga: " + getHarga());
    }
}
Class order berfungsi untuk meng-handle detail data-data dari pesanan yang dibuat oleh customer, terdapat jenis kopi yang dipilih, keterangan tambahan gula/susu, keterangan ukuran yang dipilih, dan juga keterangan harga akhir dari suatu pesanan. Selain itu, dari class ini juga nantinya akan digunakan sebagai detail log pesanan sesuai ketentuan soal.


Class VendingMachine

/**
 * Write a description of class VendingMachine here.
 *
 * @author Muhammad Zaky Zein
 * @version 14.10.2025
 */

import java.util.ArrayList;
import java.util.Scanner;

public class VendingMachine
{
    private ArrayList<Coffee> menus;
    private Stock stock;
    private ArrayList<Order> orderLog;

    public VendingMachine()
    {
        menus = new ArrayList<>();
        stock = new Stock(2, 2, 2 , 2);
        orderLog = new ArrayList<>();
        initMenu();
    }

    private void initMenu() {
        menus.add(new Coffee("Espresso", 10000));
        menus.add(new Coffee("Americano", 12000));
        menus.add(new Coffee("Latte", 18000));
    }
    
    public void start() {
        Scanner sc = new Scanner(System.in);
        int input = 1;
        while(input != 5) {
            System.out.println("Opsi:");
            System.out.println("1. Order");
            System.out.println("2. tambah stock (admin)");
            System.out.println("3. tampilkan stock (admin)");
            System.out.println("4. tampilkan log transaksi (admin)");
            System.out.println("5. keluar");
            System.out.print("Pilih 1-5:");
            input = sc.nextInt();
            if(input == 1) { makeOrder(); }
            else if(input == 2) { tambahStock(); }
            else if(input == 3) { tampilkanStock(); }
            else if(input == 4) { tampilkanLog(); }
        }

        sc.close();
    }
    
    public void showMenu() {
        System.out.println("===Menu kopi yang tersedia===");
        System.out.println("Nama       | Small | Medium | Large");
        for (Coffee coffee : menus) {
            int med = coffee.getbasePrice() + coffee.SIZE_MEDIUM;
            int lar = coffee.getbasePrice() + coffee.SIZE_LARGE;
            System.out.println(coffee.getName() + " | " + coffee.getbasePrice() + " | " + med + " | " + lar);
        }
    }

    public void makeOrder() {
        Scanner sc = new Scanner(System.in);
        int opsiMenu;
        int opsiSize;
        boolean extraGula;
        boolean extraSusu;
        int bayar;
        showMenu();
        System.out.print("Pilih menu 1-3:");
        opsiMenu = sc.nextInt();
        System.out.print("Pilih size [1 - small; 2 - medium; 3 - large]:");
        opsiSize = sc.nextInt();
        System.out.print("Tambah Gula? (+Rp500) [true; false]:");
        extraGula = sc.nextBoolean();
        System.out.print("Tambah Susu? (+Rp2000) [true; false]:");
        extraSusu = sc.nextBoolean();
        
        if(stock.checkStock(menus.get(opsiMenu - 1).getName(), extraGula, extraSusu)) {
            orderLog.add(new Order(menus.get(opsiMenu - 1), extraGula, extraSusu, opsiSize));
            System.out.println("Detail order:");
            orderLog.getLast().printLog();
            System.out.println("Bayar (" + orderLog.getLast().getHarga() + "): ");
            bayar = sc.nextInt();
            if(bayar < orderLog.getLast().getHarga()) {
                System.out.println("Pembayaran gagal, kembali ke menu utama...");
                orderLog.removeLast();
            } else {
                System.out.println("Pembayaran berhasil");
                stock.minStock(orderLog.getLast());
            }
        } else {
            System.out.println("Stock bahan kurang, admin akan datang mengisi stock...");
        }
        
        sc.close();
    }
    
    public void tambahStock() {
        Scanner sc = new Scanner(System.in);
        int bijiKopi;
        int air;
        int susu;
        int gula;
        System.out.print("tambah kopi:");
        bijiKopi = sc.nextInt();
        System.out.print("tambah air:");
        air = sc.nextInt();
        System.out.print("tambah susu:");
        susu = sc.nextInt();
        System.out.print("tambah gula:");
        gula = sc.nextInt();
        stock.tambahStock(bijiKopi, air, susu, gula);
        System.out.println("berhasil menambahkan stock, kembali ke menu utama...");
        sc.close();
    }

    public void tampilkanLog() {
        for (Order order : orderLog) {
            order.printLog();
        }
    }

    public void tampilkanStock() {
        System.out.println("Biji kopi: " + stock.getBijiKopi());
        System.out.println("Air: " + stock.getAir());
        System.out.println("Gula: " + stock.getGula());
        System.out.println("Susu: " + stock.getSusu());
    }
}
Class VendingMachine merupakan class utama yang mengatur keseluruhan alur kerja program, terdapat beberapa attribute seperti arraylist coffeee yang berfungsi untuk menyimpan list menu kopi yang tersedia. Stock adalah class yang berguna untuk mengecek ketersediaan stock bahan. Selain itu, ada arraylist order untuk menyimpan pesanan.

method initMenu() gunanya untuk menginisiasikan menu-menu yang tersedia pada vendingmachine.
method start() digunakan untuk menjalankan vending machine, loop utama program berada pada method ini, method ini akan terus melakukan perulangan dan menjalankan method lain sesuai opsi yang dipilih oleh user sampai user memilih keluar dari progam.
method showMenu() fungsinya untuk menampilkan daftar menu dengan menggunakan fitur foreach dari arraylist menu yang ada.
method tambahStock() gunanya untuk admin menambahkan stock ke dalam vending machine.
method tampilkanLog() berfungsi untuk menampikan log dari order yang sudah dilakukan.
method tampilkanStock() akan menampilkan stock yang tersisa pada vending machine.
method makeOrder() berfungsi sebagai menu interface user dalam melakukan order, user bisa memilih jenis kopi, ukuran, serta mengatur tambahan gula/susu. Setelah user menentukan ordernya, order akan ditambahkan kedalam log, jika pembayaran gagal akan dihapus dari log, namun jika berhasil maka akan tetap ditambahkan ke log dan kembali ke menu utama.


Class Stock
/**
 * Write a description of class Stock here.
 *
 * @author Muhammad Zaky Zein
 * @version 14.10.2025
 */
public class Stock
{
    // satuan 1 takaran saji
    private int bijiKopi;
    private int air;
    private int susu;
    private int gula;

    public Stock(int bijiKopi, int air, int susu, int gula) {
        this.bijiKopi = bijiKopi;
        this.air = air;
        this.susu = susu;
        this.gula = gula;
    }

    public Stock() {
        this.bijiKopi = 0;
        this.air = 0;
        this.susu = 0;
        this.gula = 0;
    }

    public void tambahStock(int bijiKopi, int air, int susu, int gula) {
        this.bijiKopi += bijiKopi;
        this.air += air;
        this.susu += susu;
        this.gula += gula;
    }

    public boolean checkStock(String name, boolean extraGula, boolean extraSusu) {
        boolean stockAvail = false;
        if(name == "Espresso") {
            if(bijiKopi >= 1) stockAvail = true;
            if(extraGula) { if(gula >= 1) stockAvail = true; else stockAvail = false; }
            if(extraSusu) { if(susu >= 1) stockAvail = true; else stockAvail = false; }
        } else if(name == "Americano") {
            if(bijiKopi >= 1 && air >= 1) stockAvail = true;
            if(extraGula) { if(gula >= 1) stockAvail = true; else stockAvail = false; }
            if(extraSusu) { if(susu >= 1) stockAvail = true; else stockAvail = false; }
        } else if(name == "Latte") {
            if(bijiKopi >= 1 && susu >= 1) stockAvail = true;
            if(extraGula) { if(gula >= 1) stockAvail = true; else stockAvail = false; }
            if(extraSusu) { if(susu >= 2) stockAvail = true; else stockAvail = false; }
        }

        return stockAvail;
    }

    public void minStock(Order o) {
        if(o.getCoffeeName().equals("Espresso")) {
            bijiKopi -= 1;
        } else if(o.getCoffeeName().equals("Americano")) {
            bijiKopi -= 1;
            air -= 1;
        } else if(o.getCoffeeName().equals("Latte")) {
            bijiKopi -= 1;
            susu -= 1;
        }
    }

    public int getBijiKopi() { return bijiKopi; }
    public int getAir() { return air; }
    public int getSusu() { return susu; }
    public int getGula() { return gula; }
}
Class Stock akan menentukan apakah vendingmachine dapat membuat order atau tidak, pada saat ini, masih hardcode karena kesalahan design program dan keterbatasan waktu. Namun, program ini masih dapat bekerja. berikut penjelasannya. Stocknya diukur berdasarkan takaran saji, bukan dalam mL, gram, dan sebagainya. terdapat beberapa method:
method tambahStock() berfungsi untuk menambahkan stock jika admin mengakses menu untuk menambah stock.
method checkStock() berfungsi untuk mengecek ketersediaan stock sebelum order diselesaikan. cara kerjanya adalah dengan mengecek ketersediaan masing-masing bahan yang diperlukan dari setiap jenis menu kopi yang tersedia, misal espresso membutuhkan biji kopi, americano membutuhkan tambahan air, latte menggunakan tambahan susu. Dengan logika if else sederhana kita bisa mengecek ketersediaannya.
method minStock() berfungsi untuk mengurangi stock jika order berhasil dilakukan (stock cukup & pembayaran berhasil).
selain method-method di atas, terdapat juga getter sederhana untuk mengakses variable variable yang sifatnya private.


Kesimpulan
Karena keterbatasan waktu, saya sempat salah untuk mendesain classnya dan harus "gali lubang, tutup lubang" pada kode diatas. Namun, sejauh ini fungsinya masih bisa dijalankan. Program lengkapnya dapat diakses di github:

Link Video


Muhammad Zaky Zein
5025241148
PBO A


Comments