Skip to content

Commit

Permalink
Merge pull request #76 from jetbrains-academy/stephen-hero-patch-1
Browse files Browse the repository at this point in the history
Update task.md
  • Loading branch information
nbirillo authored Sep 28, 2024
2 parents 587265e + 1c55295 commit 2d54fcf
Showing 1 changed file with 86 additions and 86 deletions.
172 changes: 86 additions & 86 deletions culinaryServer/culinaryServerTask1/task.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,19 @@ Master Chef - Introduction (Theory task)
### Project description


The project of this lesson is **Master Chef**.
The project for this lesson is **Master Chef**.
Have you ever dreamed of becoming a master chef?
In this application all your dreams will come true, and you will be able
to cook delicious dishes and learn programming. Isn't it great?
In this application, you'll get a chance to make that dream come true by
cooking delicious dishes while learning programming. Isn't that exciting?

### Lesson topics

- Working with pre-rewritten API
- List vs Sequence
- Working with a pre-rewritten API
- List vs. Sequence

### Project example

By the end of this task, you will create the following application:
By the end of this task, you will have created the following application:

![Final application](TODO)

Expand All @@ -25,88 +25,88 @@ Master Chef - How to Run (Theory task)

At each stage, you can run the current version of the application.
However, if some functionality is not yet ready,
then some buttons may not work and some information may not be displayed.
certain buttons may not work, and some information may not be displayed.

To run the application, you need to run the `main` function inside
To run the application, execute the `main` function inside
the [MasterChefApplication.kt](psi_element://org.jetbrains.kotlin.course.culinary.MasterChefApplicationKt#main) file:

![How to run the application](TODO)

Please don't forget to _stop all other runs_ by pressing the red square button:
Please remember to _stop any previous runs_ by pressing the red square button:

![How to stop the application](TODO)

Next, you need to open any browser (we recommend using [Google Chrome](https://www.google.com/chrome/) to display the elements as in the examples)
and open http://localhost:8080/. You will see the main page of the application.
Next, open a browser (we recommend using [Google Chrome](https://www.google.com/chrome/) to display the elements as in the examples)
and go to http://localhost:8080/. This will display the main page of the application.

<div class="hint" title="Click me to view what the main page of the application looks like">

![The main page of the application](TODO)

</div>

<div class="hint" title="Click me if the application from the last launch is displayed">
<div class="hint" title="Click me if the application from the previous launch is displayed">

If an application from a previous launch is displayed on the screen when starting the game, you need to reset the caches.
This can usually be done with a keyboard shortcut: `ctrl` + `shift` + `R` (`command` + `shift` + `R` for macOS).
If an application from a previous launch is displayed when starting the game, you may need to reset the caches.
This can usually be done with the keyboard shortcut: `ctrl` + `shift` + `R` (`command` + `shift` + `R` for macOS).
</div>

______________

Master Chef - The Kitchen, Models (Theory task)

To work in our kitchen, you need to understand what API (classes and functions) we already have,
because throughout this lesson you will be improving that API.
To work in our kitchen, you need to understand the available API (classes and functions),
as you will be enhancing this API throughout the lesson.

Firstly, we have a set of _models_ which represent all the items in our kitchen.
All models are stored in the `models' folder and are divided into three categories:
- _food_ - models that represent all the possible foods we have.
- _storage_ - models representing places where food is stored, such as a fridge or a shelf.
- _cooking_ - models representing kitchen utensils for cooking, such as a pot.
Firstly, we have a set of _models_ representing all the items in our kitchen.
These models are stored in the `models' folder and are categorized as follows:
- _food_: Models representing all possible foods.
- _storage_: Models representing storage locations, such as a fridge or a shelf.
- _cooking_: Models representing kitchen utensils, such as a pot.

Let's start with the _food_ models. Basically we have vegetables, fruits and species.
Vegetables can be fresh or not, cut or in their original form.
**Check all the possible models before going to the next steps,
it will help you when we refer to them in the tasks.**
Let's start with the _food_ models. These include vegetables, fruits, and spices.
Vegetables can be fresh or not, whole or cut.
**Familiarize yourself with all the available models before proceeding,
as this will be helpful when they are referenced in tasks.**

![Food models](TODO: picture with all possible food)

Then we have the _storage_ models.
We only have three types of storage: a fridge that can only store vegetables,
a basket for storing fruit and a shelf for storing spices.
**Check all the possible models before going to the next steps,
it will help you when we refer to them in the tasks.**
Next, we have the _storage_ models.
There are three types of storage: a fridge that can only store vegetables,
a basket for storing fruit, and a shelf for storing spices.
**Familiarize yourself with all the available models before proceeding,
as this will be helpful when they are referenced in tasks.**

![Food models](TODO: picture with all possible storages)
![Storage models](TODO: picture with all possible storages)

Finally, we have the _cooking_ models.
These will help us to cook our dishes.
These are used to cook our dishes.
As you can see, they are implemented as interfaces,
and you will be implementing some of these functions yourself during this lesson.
**Check all the possible models before going to the next steps,
it will help you when we refer to them in the tasks.**
and during the lesson, you will implement some of these functions yourself.
**Familiarize yourself with all the available models before proceeding,
as this will be helpful when they are referenced in tasks.**

![Food models](TODO: picture with all possible kitchen utensils)
![Cooking models](TODO: picture with all possible kitchen utensils)

______________

Master Chef - Fridge Refill (Coding task)


Woohoo! It's coding time! Let's start with a simple task.
To make our cooking possible, we need to refill the fridge with vegetables.
In this task we will make the `Refill` button live, which will remove all the old vegetables and add new ones.
Woohoo! Let's get coding! We'll start with a simple task:
refilling the fridge with vegetables.
In this task, you'll make the `Refill` button functional by removing old vegetables and adding new ones.

The `FridgeImpl` object has a mutable list of `vegetables` to store.
In this task you need to implement two methods inside `FridgeImpl`:
The `FridgeImpl` object contains a mutable list of `vegetables`.
In this task, you need to implement two methods inside `FridgeImpl`:

- `generateRandomVegetables` - that should build a list of `Vegetable` by the following rules:
- `generateRandomVegetables`: Generates a list of vegetables based on the following rules:

- generates `RANDOM_VEGETABLES_NUMBER` random vegetables with random value for `isFresh` property
- generates `RANDOM_FRESH_VEGETABLES_NUMBER` random not fresh vegetables (with `isFresh = True` property)
- Produces `RANDOM_VEGETABLES_NUMBER` random vegetables with random freshness (`isFresh` property).
- Produces `RANDOM_FRESH_VEGETABLES_NUMBER` random fresh vegetables (`isFresh = True` property).

- `refill` - that should clear all the vegetables from the list of `vegetables`,
generates new ones with the `generateRandomVegetables` function and add them into the list of `vegetables`
- `refill`: Clears the current list of `vegetables`,
generates new ones using the `generateRandomVegetables` function, and adds them to the list.

<div class="hint" title="Click me to view the expected state of the application after completing this task">

Expand All @@ -122,59 +122,59 @@ If you have any difficulties, **hints will help you solve this task**.

<div class="hint" title="Click me to learn how to generate a random boolean value">

To generate a random boolean value you can use [`Random.nextBoolean()`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.random/-random/next-boolean.html) function from the Kotlin standard library.
To generate a random boolean value, you can use the [`Random.nextBoolean()`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.random/-random/next-boolean.html) function from the Kotlin standard library.
</div>

______________

Master Chef - List vs. Sequence (Theory task)

The main purpose of this project is to show the difference between regular collections
(in our example `List`) with `Sequence`s.
**If you are noe familiar with Kotlin collections, we recommend you to learn them with the previous projects on this course and come back then.**
The main purpose of this project is to demonstrate the difference between regular collections
(like `List`) and `Sequence`.
**If you are not yet familiar with Kotlin collections, we recommend revisiting the previous projects in this course before continuing.**

Unlike collections, sequences _don't contain elements_, they produce them while iterating.
Sequences implement the approach to multi-step collection processing.
It means, that when you operate with sequences you combine all the operations that should be done in one action.
Unlike collections, sequences _don't contain elements_; they produce them during iteration.
Sequences implement a method for multi-step collection processing,
which means that when operating with sequences, all the operations are combined into a single action.

Consider an example with cooking.
Let's imagine that we need to cook a tomato soup.
To make it simple, we will use only tomatoes.
To ook this sup, we need to pull tomatoes from the fridge, put them into the kitchen, cut them, and then add into a pot.
Consider this example invloving cooking
tomato soup.
Let's simplify it by using only tomatoes.
To cook this soup, we need to pull tomatoes from the fridge, place them in the kitchen, cut them, and then add them to the pot.

If we work with a _list_ of tomatoes, then we will do it exactly as we described,
since we will be working with all the tomatoes per action, e.g., get all tomatoes, then cut all the tomatoes, etc:
If we work with a _list_ of tomatoes, we'll perform
each step for all the tomatoes simultaneously—pull them all out, cut them all, and so on:

![Current state](TODO: picture that describes this process)

If we work with a _sequence_ of tomatoes, then we will handle each tomato separately until we get the necessary number of tomatoes, e.g.
we will get one tomatoe, put it into the kitchen, cut it, put into the pot. Then we will repeat this action with the next tomato, and etc:
In contrast, when working with a _sequence_ of tomatoes, each tomato is handled individually until we have the required amount. For example,
we pull one tomato, place it in the kitchen, cut it, and put it into the pot before moving on to the next tomato:

![Current state](TODO: picture that describes this process)

The first approach works good in the case, when you have enough space in the kitchen, but if you don't,
probably the second one will be better - since it cn handle a long _sequence_ of tomatoes with a limited space in the kitchen.
The first approach works well if you have enough space in the kitchen, but if space is limited,
the second method might be more efficient, since it handles each tomato sequentially, requiring less space.

![Current state](TODO: picture 1 case when many tomatoes and do not have enough space on the table)
![Current state](TODO: picture 1 case with many tomatoes and not enough space on the table)

This way of computing is called `lazy computing` and it is the main idea of the sequences.
This method of computing is called `lazy computing`, which is the primary concept behind sequences.

______________

Master Chef - Cook Tomato Soup (Coding task)

Let's practice! Let's start with the familiar approach with collections cook the tomato soup from the previous lesson with a _list_ of tomatoes.
In this task we will make the `Cook Tomato Soup` button live.
Now let's practice! We'll start by using collections to cook tomato soup, as we did in the previous lesson.
In this task, you'll make the `Cook Tomato Soup` button functional.

In this task, you need to implement two functions in the `TomatoSoup.kt` file:
You need to implement two functions in the `TomatoSoup.kt` file:

- `getTomatoesForSoup` - which generates a _list_ of `NUMBER_OF_TOMATOES` tomatoes (a `VegetableType` with type `VegetableType.Tomato`)
- `prepareTomatoes` - that accept a _list_ of tomatoes, and do the following with each item frm the list:
- `getTomatoesForSoup`: Generates a _list_ of `NUMBER_OF_TOMATOES` tomatoes (a `VegetableType` with `VegetableType.Tomato`).
- `prepareTomatoes`: Accepts a _list_ of tomatoes and performs the following action for each:

- put it into the kitchen (see `KitchenImpl.put`)
- cut each element (see `KitchenImpl.cut`)
- take each cut tomato (see `KitchenImpl.take`)
- put each tomato into the pot (see `PotImpl.put`)
- Places it in the kitchen (`KitchenImpl.put`).
- Cuts the tomato (`KitchenImpl.cut`).
- Takes the cut tomato (`KitchenImpl.take`).
- Places the tomato in the pot (`PotImpl.put`).

<div class="hint" title="Click me to view the expected state of the application after completing this task">

Expand All @@ -186,30 +186,30 @@ ______________

Master Chef - Sequence Initialization (Theory task)

Let's come back to the sequences. As we mentioned before, sequences do not _store_ elements.
It influences several rules to work with the sequences:
Returning to sequences, as mentioned earlier, sequences do not _store_ elements.
This fact introduces several rules for working with them:

1) Usually the sequence is initialized by some _rule_ of how the next element will be generated. For example, if we already boiled tomatoes and want to add some species, the rule will be "extracting the next spice jar from the shelf".
1) Sequences are typically initialized with a _rule_ that dictates how the next element will be generated. For example, if we have already boiled the tomatoes and want to add some spices, the rule could be be "extract the next spice jar from the shelf".

**Note that this is not always true**, you can convert a list to a sequence to perform all actions together. But it will not be a good idea for fast operations with small collections, because you will also need to spend some resources for the conversion to sequence and back.
**Note that this rule is not always necessary**you can convert a list to a sequence to perform all actions at once. However, this isn't ideal for fast operations with small collections, as the conversion to a sequence and back requires additional resources.

2) If you work with the sequences, you always need to invoke one of the _terminal_ functions to actually run all the actions.
2) When working with sequences, you must always invoke a _terminal_ function to execute the operations.

Note, that sequences can be indefinite, so be careful when you call a _terminal_ function with no size limitation.
Note that sequences can be infinite, so be cautious when calling a _terminal_ function without a size limit.

Consider examples for both cases. Let's imagine that we need to generate a sequence of species for our tomato soup.
We can use [`generateSequence`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.sequences/generate-sequence.html) function with a condition inside:
Consider examples for both scenarios. Imagine generating a sequence of spices for our tomato soup.
We could use the [`generateSequence`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.sequences/generate-sequence.html) function with a condition:

```kotlin
val spices = generateSequence{ shelfWithSpices.getNextValidOne(...) }
```

In this case we will not actually have these `spices`, `shelfWithSpices.getNextValidOne(...)` will be called each time when it will be necessary, i.e. when we will actually need the next jar of species.
For example, if for each jar of species we need to add it into the soup and we want to add only 3 different species, it will be done in the following way:
In this case, the `spices` aren't actually retrieved until needed. Each time the next jar of spices is required, `shelfWithSpices.getNextValidOne(...)` is called.
For example, if we need to add 3 different spices to the soup, this process will be as follows:

![Current state](TODO: a picture where we get and handle each piece step by step)

Consider the second example. A _terminal_ function is necessary to show the Kotlin compiler, that you actually ready to proceed with the actions, e.g. `take(5)` or `toList()` for finite sequences.
From the example above, if we don't use `take(5)` and in theory have infinite shelf, we will not be able to handle all of them, we do have limited resources on our laptop (or in a pot from the example).
In the second example, a _terminal_ function is necessary to inform the Kotlin compiler that you are ready to proceed with the operations, such as using `take(5)` or `toList()` for finite sequences.
If we don't use `take(5)`, and if the shelf were infinite, we wouldn't be able to handle all the jars due to limited resources (whether on your laptop or in the pot from the example).

![Current state](TODO: a picture - limited size of the pot, and we cannot handle all of them)

0 comments on commit 2d54fcf

Please sign in to comment.