Skip to content

Instantly share code, notes, and snippets.

@Zubayer204
Last active November 11, 2024 06:00
Show Gist options
  • Save Zubayer204/af64d60ca2be98308b7e559f68a3bdbe to your computer and use it in GitHub Desktop.
Save Zubayer204/af64d60ca2be98308b7e559f68a3bdbe to your computer and use it in GitHub Desktop.
Kitchen Project Guidelines

Task 1: Implement the Ingredient Struct

I see you have done it correctly. You have implemented the Ingredient struct correctly.

Task 2: Modify the Dish Class

Member Variables

On Dish.hpp file, you will need to change the member variable std::vector<std::string> ingredients_; to using the Ingredient struct. like this:

std::vector<Ingredient> ingredients_;

Member functions

Now that you have chanded ingredients_ member variable from a vector of strings to a vector of Ingredient structs, you will need to change the getIngredients() and setIngredients() member functions.

getIngredients()

On Dish.hpp file, you will need to change the getIngredients() member function to return a vector of Ingredient structs.

std::vector<Ingredient> getIngredients() const;

And on Dish.cpp file, change the vector return type as well and you'll fine.

setIngredients()

On Dish.hpp file, you will need to change the setIngredients() member function to take a vector of Ingredient structs as a parameter.

void setIngredients(const std::vector<Ingredient>& ingredients);

And on Dish.cpp file, change the vector parameter type as well and you'll fine.

Task 3: Implement the KitchenStation Class

Data Members

You have done a great job declaring the private data members of the KitchenStation according to the instructions.

Constructors/Destructors

Both constructors and destructors are already implemented correctly. I don't really know if you have difficulty with understanding them. Let me know if any concept about Constructors/Destructors is not clear. Understanding those is the key to it. Everyone forgets the syntax and code, but the concept is what stays with us.

Member Functions

All the accessors getName(), setName() getDishes() and getIngredients() are implemented correctly. I see there's no documentation header for any function other than getName(). Do add those before submitting as you'll be graded on it I guess.

assignDishToStation

It seems good as well. There are other easier ways to loop through a vector but if for loop seems more natural to you, then go for it.

replenishStationIngredients

This function is implemented amazingly well. You are using the auto keyword to loop through the vector of Ingredient structs I see. You can also use for loop here like you have used in the other functions.

canCompleteOrder

There are some polishing needed here. You were headed to the right direction. below is the pseudocode for the function.

bool dish_present_in_kitchen = false;

for (each dish in dishes) {
    if dish.name == given_dish_name
        dish_present_in_kitchen = true;
        break; // we found the dish, so we can break out of this loop
}

// if dish was not present in kitchen station, we can immidietly return false
// as we cannot complete complete an order that our kitchen doesn't make
if (!dish_present_in_kitchen) return false;

// Now check if we have all the ingredients we need or not
bool single_ingredient_available_in_full_quantity;
for (every required_ingredient in dish.ingredients) {
    single_ingredient_available_in_full_quantity = false;

    for (every available_ingredient in indient_stock) {
        // check if we have that ingredient and we have equal to or more than the quantity of ingredients needed
        if (available_ingredient.name == required_ingredient) and (available_ingredient.quantity >= required_ingredient.quantiy)
            single_ingredient_available_in_full_quantity = true;
            break;
    }

    if !(single_ingredient_available_in_full_quantity) return false;
}

// if we reach this portion of the code, that mean all the ingredients were present in sufficient quantity.
// we can safely return true now
return true;

prepareDish

For this, we will first check if we canCompleteOrder. If we can, then we will find the Dish in our kitchen and loop through the required ingredients. Inside that loop, like we did in the previous function, we loop through the available ingredients and decrease its amount if we need it in the dish. We also remove that Ingredient from the vector of IngredientStock if the quantity deplets to 0. Now the pseudocode:

if (!canCompleteOrder) return false;

Dish target_dish = null;
for (every dish in dishes) {
    if dish.name == dish_name
        target_dish = dish
        break
}

required_ingredients = target_dish.getIngredients()

for (each required_ingredient in required_ingredients) {
    for (each available_ingredient in ingredient_stoc) {
        if available_ingredient.name == required_ingredient.name
            available_ingredient.quanty -= required_ingredient.quantity

        if available_ingredient.quantity <= 0:
            remove available_ingredient
    }
}

return true;

Task 4: Implement the StationManager Class

Constructors/Destructors

Your current constructor is writely written except it doesn't initialize the LinkedList class that StationManager inherited from. To do that, you need to do something like this:

StationManager::StationManager() : LinkedList<KitchenStation*>() {}

And in the destructor, since we need to delete a LinkedList of KitchenStation, we traverse through it and delete one by one. Pseudocode for that will look something like this:

KitchenStation node current = get_head_of_linked_list()

while (current node is not null) {
    delete current item;
    current = current.next;
}

Member Functions

addStation

For this, we first check if the station that was passed to us is a valid pointer or not. If not, we return false. Then we check if the station with the same name already exists. If it exists, we return false. If not, we call the insert function of our LinkedList and insert it in the head position. Below is the pseudocode for this:

FUNCTION addStation(station: KitchenStation*) RETURNS boolean
    // Check if station pointer is null
    IF station IS null THEN
        RETURN false
    END IF

    // Check if station with same name already exists
    SET current = headNode
    WHILE current IS NOT null
        IF current->data->getName() EQUALS station->getName() THEN
            RETURN false // Station with same name exists
        END IF
        SET current = current->next
    END WHILE

    // Insert station at beginning of list
    CALL insert(0, station)
    RETURN true

END FUNCTION

removeStation

For a simple check, we first see if our linked list is empty or not. If it's empty, we can return false right away and there is no need to advance further. If not, we loop through the linked lists and check if any of the KitchenStation's name matches our gieven name. If it does, we set our found flag to true and save the position (index) of it in our position variable. Then we just delete the pointer and remove it from linked list using the remove function. Below is the pseudocode for that:

FUNCTION removeStation(station_name: STRING) -> BOOLEAN
    // If list is empty, return false
    IF list is empty THEN
        RETURN false
    END IF

    // Initialize variables
    SET current_node = head node
    SET previous_node = nullptr
    SET found = false
    SET position = 0

    // Search for the station with matching name
    WHILE current_node is not null
        IF current_node's station name equals station_name THEN
            SET found = true
            BREAK
        END IF
        SET previous_node = current_node
        SET current_node = next node
        INCREMENT position
    END WHILE

    // If station not found, return false
    IF not found THEN
        RETURN false
    END IF

    // Delete the station object
    DELETE current_node's station pointer

    // Remove the node from the linked list using inherited remove function
    CALL remove(position)

    RETURN true
END FUNCTION

findStation

This is gonna be simple. We have been doing this 'finding' in all the other previous functions as well. We just get the head of the linked list and set it to variable current. Then we loop through until the 'current' variable is not null and check if the name of current kitchen station matches the given name or not. Below is the pseudocode for it.

Function findStation(station_name) -> KitchenStation*:
    // Initialize current node to head of linked list
    current = getHeadNode()

    // Traverse the linked list while current is not null
    While current is not null:
        // Get the KitchenStation pointer from current node
        station = current->getItem()

        // Check if station name matches the search parameter
        If station->getName() equals station_name:
            // Return the matching station
            Return station

        // Move to next node
        current = current->getNext()

    // If no matching station found, return nullptr
    Return nullptr

End Function

moveStationToFront

First we check if moving is necessary (list empty or has one single item). After that, we search through the list and keep track of the current and previous node of the list. If we did not find the station, we return flase immidietly. Then it is the part of moving. We check if the station we want to move is already at the front or not. If it's already at the front, there's no need to move.

For the moving part, I am trying to explain it with some flow diagrams. Suppose we have a linked list of kitchen station with names like "Prep Station", "Grill Station" and "Dessert Station". We want to move "Grill Station" to the front. This is how the linked list currently looks like:

Initial State:

graph LR
    Head --> A["Prep Station"] --> B["Grill Station"] --> C["Dessert Station"] --> null
Loading

Step by Step Movement:

  1. Find the node and its previous node:
previous = Prep Station
current = Grill Station
  1. Update previous node's next pointer to skip current:
graph LR
    Head --> A["Prep Station"] --> C["Dessert Station"] --> null
    B["Grill Station"]
Loading
  1. Set current node's next pointer to head:
graph LR
    Head --> A["Prep Station"] --> C["Dessert Station"] --> null
    B["Grill Station"] --> A
Loading
  1. Update head pointer to current:
graph LR
    Head --> B["Grill Station"] --> A["Prep Station"] --> C["Dessert Station"] --> null
Loading

Pseudocode for this will look something like this:

moveStationToFront(station_name):
    // If list is empty or has only one node, return false
    IF getLength() <= 1 THEN
        RETURN false
    END IF

    // Initialize pointers
    SET current = getHeadNode()
    SET previous = nullptr
    SET found = false

    // Search for the station with matching name
    WHILE current is not nullptr DO
        IF current->getItem()->getName() equals station_name THEN
            SET found = true
            BREAK
        END IF
        SET previous = current
        SET current = current->getNext()
    END WHILE

    // If station not found, return false
    IF not found THEN
        RETURN false
    END IF

    // If station is already at front, return false
    IF previous is nullptr THEN
        RETURN false
    END IF

    // Move the station to front
    previous->setNext(current->getNext())
    current->setNext(getHeadNode())
    SET head_ptr_ = current

    RETURN true
END FUNCTION

mergeStations

For this, we first check if both the stations exists or not. Then just add all ingredients from station 2 to station 1 and then delete station 2.

function mergeStations(station_name1, station_name2):
    // Find both stations in the list
    station1 = findStation(station_name1)
    station2 = findStation(station_name2)

    // If either station doesn't exist, return false
    if station1 is null OR station2 is null:
        return false

    // Merge dishes from station2 into station1
    for each dish in station2's dishes:
        add dish to station1's dishes

    // Merge ingredients from station2 into station1
    for each ingredient in station2's ingredients:
        if ingredient exists in station1:
            add quantities together
        else:
            add new ingredient to station1

    // Remove station2 from the list
    removeStation(station_name2)

    return true

assignDishToStation

This is a simple function that needs to just finding the Station and assigning a dish

FUNCTION assignDishToStation(station_name: STRING, dish: DISH*) RETURNS BOOLEAN
    // Find the station with the given name
    station = findStation(station_name)

    // If station not found, return false
    IF station IS NULL THEN
        RETURN false
    END IF

    // Try to assign the dish to the found station
    RETURN station->assignDishToStation(dish)
END FUNCTION

replenishIngredientAtStation

Plain and simple like the previous function. Just find the station and call the replenish method on it.

function replenishIngredientAtStation(station_name, ingredient):
    // Find the station with the given name
    station = findStation(station_name)

    // If station not found, return false
    if station is nullptr:
        return false

    // Call the station's replenishStationIngredients method
    station->replenishStationIngredients(ingredient)

    // Return true since operation was successful
    return true

end function

canCompleteOrder

For this, we need to loop through all the stations and call the canCompleteOrder on it. As soon as we find any station that returns true, we return true as well.

canCompleteOrder(dish_name):
    current_station = head()
    while (current_station is not null)
        if current_station->canCompleteOrder(dish_name)
            return true

        current_station = current_station.next()

    // Since we have reached this point, that means no station can complete this order
    return false;

prepareDish

At first, we find the station and then call prepareDish method on that KitchenStation instance.

prepareDish(station_name, dish_name):

    station = findStation(station_name);

    if (station = nullptr)
        return false;

    return station->prepareDish(dish_name);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment