This is a restaurant order management platform designed to handle concurrent order processing, storage optimization, and delivery management.
The system processes orders through multiple states (pre-processing, cooking, placement, and delivery) while managing temperature-controlled storage units (Heater, Cooler, and Shelf).
-
On the web app, real-time updates via SignalR keep you informed of every order status change, and the intelligent placement algorithm ensures orders are stored at optimal temperatures to maintain freshness and meet delivery time requirements.
-
On the console app, you can see logs from different order states and threads.
- Order comes in either from API or a Random generator.
- We pre-process the order (set delivery time in seconds).
- Cook the order. Current set-up: instantly.
- Place the order in either heater, cooler or shelf based on the preffered temperature.
- When delivery time is due, we either deliver the order or discard it (if order freshness is 0).
Now, if a preffered storage place for an order is full, we try to:
- place it on the shelf;
- discard an existing item on the shelf based on the discard criteria (more on it below);
- move an hot/cold item from shelf to a preffered location (if there's enough room);
- Real-time processing
- Random Order generation
- Unit Tests and Integration tests
- Web and Console interfaces
- Serilog logging for all order states
In order to process orders in real-time, we are using threads.
| Thread name | Description |
|---|---|
| ThreadFreshness | Removes freshness points from orders every 1 sec. |
| ThreadListSizes | Prints heater, cooler and shelf item counts. |
| ThreadPickupTime | Removes pickup time from orders every 1 sec. |
| Main thread | Processes the orders |
public string Id { get; set; } // Unique 5 digit id.
public string Name { get; set; } // Dish name
public OrderTypeEnum OrderType { get; set; } // Order type: Hot, Cold or Room
public long Price { get; set; }
public long Freshness { get; set; } // Freshness in seconds. If it's 0 when order is about to get delivered, we discard it.
public int PickupTime { get; set; } // When the order is to be delivered.
public OrderStoragePlaceEnum CurrentLocation { get; set; } // Where Order is stored (Heater, Cold, Shelf)I use order state pattern from here.
- Pre-process Order State - performs initial order processing (sets delivery time).
- Cook Order State - cooks the order.
- Place Order State - places the order on the heater, cooler or shelf.
- Move Order State - moves order from shelf to heater/cooler and/or discards an existing order to make space.
- Pick Order State - delivers an order.
- Discard Order State - removes an order.
We are receiving orders every 500 ms with varying delivery times (4-8 seconds).
We really don't want to discard orders that are about to get delivered (delivery time is close to 0), as we would lose:
- the money for the order,
- the work of the kitchen,
- ingredients
- storage space
- processing time
- delivery people's time & effort
- etc.
Also, when it comes to user experience (a user has placed an order), we want to discard an order:
- that has a long pickup time in order
So we could inform the user soon and let the user order something from us again.
Thus, my first discard strategy is to discard a single hot/cold order from the shelf with the highest pickup time.
My second discard strategy (if we can't execute the first strategy) is to discard a room temperature order with the highest pickup time.
- I'm constantly saving a single hot/cold order (inside a shelf storage area) with highest pickup time inside
HotOrColdShelfItemsDictionary.cs. - I'm also saving a room temperature highest pickup time order.
You can run the .NET solution in a couple of ways:
If dotnet 10.0 locally installed, run the program directly for convenience.
- cd into
srcdirectory
cd src
- Run the project using dotnet CLI.
dotnet run --project CSS.Challenge.Application
- Open
CSS.Challenge.slnxsolution file. - Right click on
CSS.Challenge.Applicationand clickSet as Startup Project. - Run the project
CSS.Challenge.Applicationcouple of times to get different test cases.
- Open
CSS.Challenge.slnxsolution file. - Right click on
CSS.Challenge.Weband clickSet as Startup Project. - Run the project
CSS.Challenge.Web.
The Dockerfile defines a self-contained C# reference environment.
- cd into
srcdirectory
cd src
-
Make sure the Docker is running.
-
Build the docker image.
docker build -t challenge .
- Run the docker container.
$ docker run -p "3001:8080" challenge
To run tests, run the following command using dotnet CLI:
dotnet test


