GithubHelp home page GithubHelp logo

muhammadbadrul1234 / eldorado-travel-and-tour-management-system Goto Github PK

View Code? Open in Web Editor NEW
17.0 2.0 6.0 15.02 MB

The main purpose of this system is to provide a efficient way for a customer to book hotels, flight, train and bus. Also it automates the processes and activities of a travel agency.

License: MIT License

Java 100.00%
consolebase-application java-project object-oriented-programming-project university-course-project

eldorado-travel-and-tour-management-system's People

Contributors

muhammadbadrul1234 avatar takrimchy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

eldorado-travel-and-tour-management-system's Issues

Bad Coding Smells concerns: Data Clumps

THIS ISSUE IS POSTED AS A COLLEGE ASSIGNMENT ON BAD CODING SMELLS AND REFACTORING TECHNIQUES, PLEASE CLOSE THIS ISSUE IF IT'S OF NO USE.

I found some bad smells in your coding, so i tried to fix them by refactoring some parts of it.

To eliminate the bad smell of "data clumps" in the class MongoDB.java we can apply "Extract Class" and "Replace Temp with Query", you can create a class that represents the information of the documents (for example, a Bus or Train), and then Use this class instead of passing multiple parameters in this way the vehicle data is better organized.

public class TransportInfo {
    private String from;
    private String to;
    private String name;
    private String type;
    private String time;
    private int fare;
    private int ticketAvailability;
}

Next, we adjust the mongoDBBusFinder and mongoDBTrainFinder methods to use this new class and apply "Replace Temp with Query" to improve code readability:

public class MongoDBFinder {
    ArrayList<Integer> mongoDBBusFinder(String from, String to) {
        int sum = 1;
        ArrayList<Integer> array = new ArrayList<>();
        for (Document doc : iterdocbus) {
            if (doc.get("To").equals(to)) {
                TransportInfo busInfo = createBusInfo(doc, from);
                array.add(busInfo.getFare());
                displayTransportInfo(sum, busInfo);
                sum++;
            }
        }
        return array;
    }

    ArrayList<Integer> mongoDBTrainFinder(String from, String to) {
        int sum = 1;
        ArrayList<Integer> array2 = new ArrayList<>();
        for (Document doc : iterdoctrain) {
            if (doc.get("To").equals(to)) {
                TransportInfo trainInfo = createTrainInfo(doc, from);
                array2.add(trainInfo.getFare());
                displayTransportInfo(sum, trainInfo);
                sum++;
            }
        }
        return array2;
    }

    private TransportInfo createBusInfo(Document doc, String from) {
        return new TransportInfo(from, doc.get("To").toString(), doc.get("Bus").toString(),
                doc.get("Time").toString(), Integer.parseInt(doc.get("Fare").toString()),
                Integer.parseInt(doc.get("TicketAvail").toString()));
    }

    private TransportInfo createTrainInfo(Document doc, String from) {
        return new TransportInfo(from, doc.get("To").toString(), doc.get("Train").toString(),
                doc.get("Class").toString(), doc.get("Time").toString(),
                Integer.parseInt(doc.get("Fare").toString()), Integer.parseInt(doc.get("TicketAvail").toString()));
    }

    private void displayTransportInfo(int sum, TransportInfo transportInfo) {
        System.out.print("\n\t\t\t\t|");
        System.out.format("%5s%10s%10s%20s%20s%6s%4s%4s", sum + "\t|", transportInfo.getFrom(),
                "-" + transportInfo.getTo() + "\t|", transportInfo.getName() + "\t|", transportInfo.getType() + "\t|",
                transportInfo.getTime() + "\t|", transportInfo.getFare() + "\t|\t", transportInfo.getTicketAvailability() + "\t|");
    }
}

Bad Coding Smells concerns: Duplicate Code

THIS ISSUE IS POSTED AS A COLLEGE ASSIGNMENT
I recommend applying the "Replace Type Code with State/Strategy" refactoring technique in this code. The current implementation uses a switch statement to handle different verification options in the verification method. By employing the State/Strategy pattern, you can replace this switch statement with a set of strategy classes, each representing a specific verification option. This approach enhances maintainability, readability, and adheres to the Single Responsibility Principle.
The refactored code introduces a set of VerificationStrategy classes, each encapsulating the behavior for a specific verification option. The YourClass class now uses a VerificationStrategy interface and a getVerificationStrategy method to select the appropriate strategy based on the user's choice. This design promotes extensibility, making it easier to add new verification options without modifying existing code.
Refactored Code:

import java.util.Scanner;

class YourClass {
    private static final Scanner scan = new Scanner(System.in);

    void verification() {
        clearConsole();
        new UserInterface().logo();
        System.out.println("\t\t\t\t\t\t======================================================");
        System.out.println("\t\t\t\t\t\t|                        User                        |");
        System.out.println("\t\t\t\t\t\t|         Please Select from the option Below        |");
        System.out.println("\t\t\t\t\t\t******************************************************");
        System.out.println("\t\t\t\t\t\t|               1. Visa Verification                 |");
        System.out.println("\t\t\t\t\t\t|               2. Passport Verification             |");
        System.out.println("\t\t\t\t\t\t|               3. Covid Certificate Verification    |");
        System.out.println("\t\t\t\t\t\t|               4. Return To Homepage                |");
        System.out.println("\t\t\t\t\t\t******************************************************");

        int choice = scan.nextInt();
        VerificationStrategy strategy = getVerificationStrategy(choice);
        strategy.verify();
    }

    private VerificationStrategy getVerificationStrategy(int choice) {
        switch (choice) {
            case 1:
                return new VisaVerificationStrategy();
            case 2:
                return new PassportVerificationStrategy();
            case 3:
                return new CovidCertificateVerificationStrategy();
            case 4:
                return new ReturnToHomepageStrategy(this);
            default:
                return new DefaultVerificationStrategy(this);
        }
    }

    private void clearConsole() {
        System.out.print("\033[H\033[2J");
    }
}

interface VerificationStrategy {
    void verify();
}

class VisaVerificationStrategy implements VerificationStrategy {
    @Override
    public void verify() {
        // Implementation for Visa Verification
    }
}

class PassportVerificationStrategy implements VerificationStrategy {
    @Override
    public void verify() {
        // Implementation for Passport Verification
    }
}

class CovidCertificateVerificationStrategy implements VerificationStrategy {
    @Override
    public void verify() {
        // Implementation for Covid Certificate Verification
    }
}

class ReturnToHomepageStrategy implements VerificationStrategy {
    private final YourClass yourClass;

    public ReturnToHomepageStrategy(YourClass yourClass) {
        this.yourClass = yourClass;
    }

    @Override
    public void verify() {
        yourClass.frontPage();
    }
}

class DefaultVerificationStrategy implements VerificationStrategy {
    private final YourClass yourClass;

    public DefaultVerificationStrategy(YourClass yourClass) {
        this.yourClass = yourClass;
    }

    @Override
    public void verify() {
        yourClass.verification();
    }
}

class UserInterface {
    // ... (existing code)
}

Bad Coding Smells concerns: Switch Statement

THIS ISSUE IS POSTED AS A COLLEGE ASSIGNMENT
I recommend employing the "Replace Conditional with Polymorphism" refactoring technique. Instead of relying on a switch statement to handle menu options, consider creating separate classes for each option that implement a common interface (e.g., MenuOption). This approach embraces polymorphism, allowing each class to encapsulate its specific behavior, thereby adhering to the Single Responsibility Principle. The refactoring not only enhances modularity and readability but also promotes extensibility, making it easier to incorporate new menu options without modifying existing code. This strategy aligns with recognized principles of object-oriented design and facilitates the creation of a more maintainable and scalable codebase.
Refactored Code :

import java.util.Scanner;

public class FrontPage {
    private static final Scanner scan = new Scanner(System.in);

    public static void main(String[] args) {
        frontPage();
    }

    private static void frontPage() {
        clearConsole();
        showLogo();
        showFrontMenu();
        int menu = getUserChoice();
        handleMenuOption(menu);
    }

    private static void clearConsole() {
        System.out.print("\033[H\033[2J");
    }

    private static void showLogo() {
        ShowLogo.show();
    }

    private static void showFrontMenu() {
        FrontMenu.show();
    }

    private static int getUserChoice() {
        System.out.print("Enter your choice: ");
        return scan.nextInt();
    }

    private static void handleMenuOption(int menu) {
        MenuOption option;
        switch (menu) {
            case 1:
                option = new UserLoginOption();
                break;
            case 2:
                option = new EmergencyHelpOption();
                break;
            case 3:
                option = new VerificationOption();
                break;
            case 4:
                option = new AdminLoginOption();
                break;
            case 5:
                option = new AboutOption();
                break;
            case 6:
                option = new ExitOption();
                break;
            case 7:
                option = new UsersLoginOption();
                break;
            default:
                option = new DefaultOption();
                break;
        }
        option.execute();
    }
}

interface MenuOption {
    void execute();
}

class UserLoginOption implements MenuOption {
    @Override
    public void execute() {
        new User().login();
    }
}

class EmergencyHelpOption implements MenuOption {
    @Override
    public void execute() {
        new EmergencyHelp().execute();
    }
}

class VerificationOption implements MenuOption {
    @Override
    public void execute() {
        new Verification().execute();
    }
}

class AdminLoginOption implements MenuOption {
    @Override
    public void execute() {
        new User().adminLogin();
    }
}

class AboutOption implements MenuOption {
    @Override
    public void execute() {
        new UserInterface().about();
    }
}

class ExitOption implements MenuOption {
    @Override
    public void execute() {
        new UserInterface().exit();
    }
}

class UsersLoginOption implements MenuOption {
    @Override
    public void execute() {
        new Application().usersLogin();
    }
}

class DefaultOption implements MenuOption {
    @Override
    public void execute() {
        FrontPage.frontPage();
    }
}

Bad Coding Smells concerns: Long Method

THIS ISSUE IS POSTED AS A COLLEGE ASSIGNMENT ON BAD CODING SMELLS AND REFACTORING TECHNIQUES, PLEASE CLOSE THIS ISSUE IF IT'S OF NO USE.

I found some bad smells in your coding, so i tried to fix them by refactoring some parts of it.

To refactor the method busdestination() in the class Transportation.java, remove the "long method" and apply "Extract method" and "Enter Parameter Object" to refactor.

Extract Method:
Split the method into several smaller methods with descriptive names. This improves the readability and maintainability of the code.

void busdestination() {
    Scanner scan = new Scanner(System.in);
    String destination;
    String to;
    System.out.print("\t\t\t\t\t\t Enter Start Point:");
    to = scan.nextLine();
    System.out.print("\t\t\t\t\t\t Enter Destination:");
    destination = scan.nextLine();
    
    new UserInterface().loadingBar();
    clearScreenAndDisplayLogo();
    showAvailableBuses(destination);
    int num1 = getBusSelection(scan);
    int num2 = getTicketQuantity(scan);
    processOrder(to, destination, num1, num2);
}

private void clearScreenAndDisplayLogo() {
    System.out.print("\033[H\033[2J");
    logo.logo();
}

private void showAvailableBuses(String destination) {
    System.out.println("\t\t\t\t\t\tThe Available Buses list According to Your Destination:  ");
    System.out.print(
            "\t\t\t\t_________________________________________________________________________________________\n");
    System.out.print(
            "\t\t\t\t|   SL  |         Route         |           Bus Name    |  Time | Fare  |AvailableTicket|");
    System.out.print(
            "\n\t\t\t\t+---------------------------------------------------------------------------------------+");
    displayBusDetails(destination);
    System.out.print(
            "\n\t\t\t\t+---------------------------------------------------------------------------------------+\n");
}

private void displayBusDetails(String destination) {
    ArrayList<Integer> Fares = new MongoDB().mongoDBBusFinder(to, destination);
    // display bus details using Fares
}

private int getBusSelection(Scanner scan) {
    System.out.print("\t\t\t\t Which one do you want to buy       : ");
    return scan.nextInt();
}

private int getTicketQuantity(Scanner scan) {
    System.out.print("\t\t\t\t How many Tickets do you want to buy: ");
    return scan.nextInt();
}

private void processOrder(String to, String destination, int num1, int num2) {
    ArrayList<Integer> Fares = new MongoDB().mongoDBBusFinder(to, destination);
    int cost = Fares.get(num1 - 1) * num2;
    displayOrderConfirmation(cost);
}

private void displayOrderConfirmation(int cost) {
    System.out.print(
            "\n\t\t\t\t_________________________________________________________________________________________");
    System.out.print(
            "\n\t\t\t\t|                             Order Taken Successfully                                  |");
    System.out.print(
            "\n\t\t\t\t|   Please Press Enter Key to Confirm your Purchase. Your bank Account will be Charged  |");
    System.out.print(
            "\n\t\t\t\t|_______________________________________________________________________________________|\n");
    new UserInterface().promptEnterKey();

    System.out.print("\t\t\t\t " + cost);
}

Enter Parameter Object:
Group the related parameters into an object and pass it as a single parameter to the method.

class BusOrder {
    String startLocation;
    String destination;
    int busSelection;
    int ticketQuantity;
    
    // Constructor, getters, and setters
}

void busdestination() {
    Scanner scan = new Scanner(System.in);
    BusOrder busOrder = getBusOrder(scan);
    
    new UserInterface().loadingBar();
    clearScreenAndDisplayLogo();
    showAvailableBuses(busOrder.getDestination());
    processOrder(busOrder);
}

private BusOrder getBusOrder(Scanner scan) {
    BusOrder busOrder = new BusOrder();
    System.out.print("\t\t\t\t\t\t Enter Start Point:");
    busOrder.setStartLocation(scan.nextLine());
    System.out.print("\t\t\t\t\t\t Enter Destination:");
    busOrder.setDestination(scan.nextLine());
    
    busOrder.setBusSelection(getBusSelection(scan));
    busOrder.setTicketQuantity(getTicketQuantity(scan));
    
    return busOrder;
}

private void processOrder(BusOrder busOrder) {
    ArrayList<Integer> Fares = new MongoDB().mongoDBBusFinder(busOrder.getStartLocation(), busOrder.getDestination());
    int cost = Fares.get(busOrder.getBusSelection() - 1) * busOrder.getTicketQuantity();
    displayOrderConfirmation(cost);
}

Also the conditionals you are using are hard to understand, you coul "Decompose Conditional" as a possible solution.

void busdestination() {
    Scanner scan = new Scanner(System.in);
    BusOrder busOrder = getBusOrder(scan);

    new UserInterface().loadingBar();
    clearScreenAndDisplayLogo();
    showAvailableBuses(busOrder.getDestination());

    if (confirmOrder(scan)) {
        processOrder(busOrder);
    }
}

private boolean confirmOrder(Scanner scan) {
    System.out.print("\t\t\t\t Do you want to confirm your purchase? (Y/N): ");
    String confirmation = scan.next().toUpperCase();
    return confirmation.equals("Y");
}

// Rest of the methods remain the same...

Factory Pattern

The Factory pattern allows you to encapsulate object creation logic. This is useful when you need to instantiate different classes depending on the program conditions, in this case the hotel type. Attached UML:
image
Positive Consequences:

  • By creating separate factories for international and domestic hotels, you can avoid code duplication and make it easier to manage differences in booking processes, pricing structures, and regulations. This reduces the complexity of your code and simplifies future maintenance and updates.
  • The factory pattern allows you to easily add new types of hotels without modifying existing code. You can simply create new factories for different hotel categories (e.g., luxury, budget, all-inclusive) or specific regions. This makes your application more flexible and adaptable to changing business needs.

Negative Consequences:

  • Implementing the factory pattern requires additional upfront design and development effort. You need to define separate interfaces and factories for different hotel types, which can add complexity to your codebase, especially for smaller projects.

Redesign applying the Facade pattern

The suggestion is to apply the Facade pattern to the existing code by creating the InmigrationFacade class to simplify the interface and enhance modularity. This class will act as a unified interface, encapsulating the complexities of the CovidRegistration, MedicalTest, TbTestsStatus, and TravelGuide classes. The proposal involves providing cohesive methods in InmigrationFacade, such as registerForCovid, medicalTest, tbTestsStatus, and travelGuide, hiding the internal complexity. This approach not only simplifies the user experience but also improves code maintainability by isolating the underlying classes and facilitating future updates.

Consequences:
• Simplified Interface: End-users will interact with a unified and coherent interface, reducing complexity and enhancing understanding of immigration functionalities.
• Improved Maintainability: Isolating underlying classes facilitates future modifications and updates to internal implementations without affecting the external interface.
• Increased Modularity: The introduction of InmigrationFacade enhances system modularity by providing a clear entry point and separating responsibilities of specialized classes.

Solution in UML:
image

Front Page Design

-User Login
-International Travel
-Domestic Travel
-New User? Registration Here
-Administrator Login
-Emergency Help
-About Us
-Exit

SQL
{insert into MOCK_DATA (User Number, Name, gender, Passport Number, Phone Number, Email, Card Number, Visa ID, City, Country, User_Name, Passeord) values (1000, 'Shena Johnston', 'Genderfluid', '62756-182', '+880-429-965-7163', '[email protected]', '3562056019270988', '372-97-9599', 'Bogra', 'Bangladesh', 'sjohnstonrr', 'IOLR36qu3hC3');}
(Use Switch Statement)
(Use Same Package)

Bad Coding Smells concerns: Divergent Change

THIS ISSUE IS POSTED AS A COLLEGE ASSIGNMENT
I recommend applying the "Introduce Null Object" refactoring technique. In the HotelRentalSystem code, the NullOption class is used as a placeholder to represent the default case when an invalid menu option is chosen. By introducing a null object instead of creating a new instance of NullOption, you can simplify the code and eliminate the need for a separate class. This approach makes the code cleaner and reduces the complexity associated with handling null cases.
Refactored Code:

import java.util.Scanner;

class Hotel {
    void guestProfile() {
        System.out.println("Executing guestProfile");
    }

    void guestDestination() {
        System.out.println("Executing guestDestination");
    }

    void guestPurchase() {
        System.out.println("Executing guestPurchase");
    }

    void guestProfileView() {
        System.out.println("Executing guestProfileView");
    }

    void guestExit() {
        System.out.println("Executing guestExit");
    }
}

public class HotelRentalSystem {
    private static final Scanner scan = new Scanner(System.in);

    public static void main(String[] args) {
        HotelRentalSystem system = new HotelRentalSystem();
        system.domesticHotelRental();
    }

    void domesticHotelRental() {
        int choice, n = 1;

        System.out.println("\t\t\t\t\t\t======================================================");
        System.out.println("\t\t\t\t\t\t|         ** HOTEL RENTAL AND ROOM BOOKING SYSTEM   **");
        System.out.println("\t\t\t\t\t\t******************************************************");
        System.out.println("\t\t\t\t\t\t|               1. Profile Creation                  |");
        System.out.println("\t\t\t\t\t\t|               2. Destination                       |");
        System.out.println("\t\t\t\t\t\t|               3. Booking & Payment                 |");
        System.out.println("\t\t\t\t\t\t|               4. View Profile                      |");
        System.out.println("\t\t\t\t\t\t|               5. Exit                              |");
        System.out.println("\t\t\t\t\t\t******************************************************");

        System.out.println("Enter Your Choice: ");
        choice = scan.nextInt();

        Hotel hotel = new Hotel();
        n += executeMenuOption(choice, n, hotel);
        System.out.println("n: " + n); // Solo para verificar el resultado
    }

    private int executeMenuOption(int choice, int n, Hotel hotel) {
        switch (choice) {
            case 1:
                hotel.guestProfile();
                return 1;

            case 2:
                hotel.guestDestination();
                return 1;

            case 3:
                hotel.guestPurchase();
                return 1;

            case 4:
                hotel.guestProfileView();
                return 1;

            case 5:
                hotel.guestExit();
                return 0;

            default:
                return 0;
        }
    }
}

Emergency Help

Create new class
-Hospital(Subclass/Method)
-Police(Subclass/Method)
-Fire Service(Subclass/Method)
-Ambulance(Subclass/Method)
-Return to Previous Menu

Package Name: com.cse2214.eldorado

(Use Switch Statement)
(Use Break Statement)
(Use Same Package)

Redesing applying the Decorator pattern

Proposal:
The Decorator pattern would be advantageous when implementing a payment processing system that requires adding additional functionalities, such as discounts, taxes, or specific validations, without altering the original structure of the payment process.

Consequences:
By employing the Decorator pattern, a more flexible and modular design is achieved, allowing the incremental incorporation of new functionalities. This reduces the risk of introducing errors when adding new features, as modifications are confined to specific decorator classes. However, it is crucial to manage the decorator hierarchy effectively to avoid excessive complexities. The gained flexibility may lead to increased complexity if not handled carefully, but overall, the Decorator pattern offers an elegant solution for efficiently extending functionality.

Solution in UML:
image

Singleton Pattern

The Singleton pattern could be used to centralize and manage information related to immigration processes in a single instance. It provides global access to functions such as medical registration, document verification, and travel guidance, facilitating consistent interaction with immigration data. Attached UML:
image

Positive Consecuences:

  • Ensures a single access point to the TravelGuideBuilder instance, avoiding the creation of multiple instances and ensuring consistency in the construction of the object.
  • By ensuring that only one instance exists, you save memory and processing resources that would be used to create additional unnecessary instances.
    Negative Consecuences:
  • It can introduce strong coupling into the code, as the Singleton pattern can be globally accessible, which can make components directly depend on it.

Loading Animation

void loading()
{

cout<<"\n\n\n\n\t\t\t\t\t\t\t\t\tLoading\n\n\t\t\t\t\t\t";

char x=219;

for(int i=0;i<50;i++)
{
    cout<<x;

    if(i<10)
    {
        Sleep(150);

    }


    if(i>=10 && i<20)
    {
        Sleep(20);

    }


    if(i>=10)
    {
        Sleep(5);

    }

}

}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.