Created
April 20, 2021 20:27
-
-
Save iamsardorbek/051419f540d92e5006284e7be3370199 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <queue> | |
#include <fstream> | |
#define TIMESTAMP_A 2000 //milliseconds | |
#define TIMESTAMP_B 200 //milliseconds | |
#include <thread> | |
#include <mutex> | |
#include <map> | |
#include <chrono> | |
#include <unistd.h> | |
#define SMALL_SHOP_PROBLEM_ID 0 | |
#define SMALL_SHOP_N_OVENS 1 | |
#define SMALL_SHOP_TIMESTAMPS_LARGE_PIZZA 8 | |
#define SMALL_SHOP_TIMESTAMPS_SMALL_PIZZA 5 | |
#define LARGE_SHOP_PROBLEM_ID 1 | |
#define LARGE_SHOP_N_OVENS 4 | |
#define LARGE_SHOP_TIMESTAMPS_LARGE_PIZZA 6 | |
#define LARGE_SHOP_TIMESTAMPS_SMALL_PIZZA 4 | |
#define TIMESTAMPS_TO_EAT_LARGE_PIZZA 6 | |
#define TIMESTAMPS_TO_EAT_SMALL_PIZZA 4 | |
int problem_id, n_ovens, timestamps_large_pizza_cooking, timestamps_small_pizza_cooking; | |
using namespace std; | |
class Order{ | |
public: | |
int number_of_customers; | |
int index; | |
int issue_time; | |
int n_customers; | |
int n_large_pizzas_ordered; | |
int n_small_pizzas_ordered; | |
int n_large_pizzas_ready = 0; | |
int n_small_pizzas_ready = 0; | |
Order(int index_p, int issue_time_p, int number_of_customers_p, int n_large_pizzas_ordered_p, int n_small_pizzas_ordered_p) | |
{ | |
index = index_p; | |
issue_time = issue_time_p; | |
number_of_customers = number_of_customers_p; | |
n_large_pizzas_ordered = n_large_pizzas_ordered_p; | |
n_small_pizzas_ordered = n_small_pizzas_ordered; | |
} | |
void increment_large_pizzas_ready() | |
{ | |
n_large_pizzas_ready++; | |
} | |
void increment_small_pizzas_ready() | |
{ | |
n_small_pizzas_ready++; | |
} | |
bool is_order_completed() | |
{ | |
if(n_large_pizzas_ordered == n_large_pizzas_ready and n_small_pizzas_ordered == n_small_pizzas_ready) | |
{ | |
return true; | |
} | |
else | |
{ | |
return false; | |
} | |
} | |
}; | |
enum pizza_status_enum {not_ready, ready}; | |
enum pizza_size_enum {SMALL, LARGE}; | |
class Pizza{ | |
public: | |
int time_to_eat; | |
Order *order; | |
pizza_size_enum pizza_size; | |
pizza_status_enum status; | |
Pizza(pizza_size_enum pizza_size, Order * order_param) // not sure ab pointers here | |
{ | |
this->pizza_size = pizza_size; | |
order = order_param; //not sure about pointers here | |
if(pizza_size == pizza_size_enum::LARGE) | |
{ | |
time_to_eat = TIMESTAMPS_TO_EAT_LARGE_PIZZA; | |
} | |
else if(pizza_size == pizza_size_enum::SMALL) | |
{ | |
time_to_eat = TIMESTAMPS_TO_EAT_SMALL_PIZZA; | |
} | |
status = pizza_status_enum::not_ready; | |
} | |
}; | |
enum oven_status_enum {COOKING, EMPTY}; | |
class Oven{ | |
public: | |
queue <Pizza> pizzas; | |
oven_status_enum status; | |
int queue_total_time; | |
Oven() | |
{ | |
queue_total_time = 0; | |
status = oven_status_enum::EMPTY; | |
} | |
}; | |
class Table{ | |
public: | |
int capacity_people; | |
int free_spaces; | |
Table(int cap_ppl) | |
{ | |
capacity_people = cap_ppl; | |
free_spaces = cap_ppl; | |
} | |
Table() | |
{ | |
} | |
}; | |
queue <Order> orders; | |
Table tables[11]; | |
vector<Oven> ovens; | |
vector<thread> threads_to_be_joined; | |
mutex mtx_cout, mtx_orders, mtx_tables, mtx_ovens; | |
int find_least_busy_oven() | |
{ | |
int min_queue_time = 10000000, index = 0; | |
for(int i = 0; i < ovens.size(); i++) | |
{ | |
Oven oven = ovens.at(i); | |
if(oven.queue_total_time < min_queue_time) | |
{ | |
min_queue_time = oven.queue_total_time; | |
index = i; | |
} | |
} | |
return index; | |
} | |
void group_of_customers_on_a_table_func(Order order, Table & table, int table_index) | |
{ | |
mtx_cout.lock(); | |
cout<<"Customers of order #"<<order.index<<" are starting to eat on table #"<<table_index<<endl; | |
mtx_cout.unlock(); | |
usleep(((float)(order.n_large_pizzas_ordered * TIMESTAMPS_TO_EAT_LARGE_PIZZA) / order.number_of_customers + (float)(order.n_small_pizzas_ordered * TIMESTAMPS_TO_EAT_SMALL_PIZZA) / order.number_of_customers)* TIMESTAMP_B); | |
mtx_tables.lock(); | |
table.free_spaces += order.number_of_customers; | |
mtx_tables.unlock(); | |
//order is fully complete | |
mtx_cout.lock(); | |
cout<<"Customers of order #"<<order.index<<" finished eating on table #"<<table_index<<endl; | |
mtx_cout.unlock(); | |
} | |
void find_relevant_table(Order & order) | |
{ | |
while(true) | |
{ | |
mtx_cout.lock(); | |
cout<<"Finding a table for customers of order #"<<order.index<<endl; | |
mtx_cout.unlock(); | |
//cout<<"order->n_customers = "<<order.number_of_customers<<endl; | |
int min_dif = 100000, index = 0; | |
bool found_free_table = false; | |
for(int i = 0; i < 11; i++) | |
{ | |
//cout<<"i = "<<i<<", tables[i].free_spaces - order->n_customers = "<<(tables[i].free_spaces - order->number_of_customers)<<endl; | |
if(tables[i].free_spaces >= order.number_of_customers and (tables[i].free_spaces - order.number_of_customers) < min_dif) | |
{ | |
index = i; | |
found_free_table = true; | |
min_dif = tables[i].free_spaces - order.number_of_customers; | |
} | |
} | |
if(found_free_table) | |
{ | |
mtx_cout.lock(); | |
cout<<"Finding a table for customers of order #"<<order.index<<" | "<<"Relevant table was found"<<endl; | |
cout<<"Table with index #"<<index<<", has "<<tables[index].free_spaces<<" free spaces. There are "<<order.number_of_customers<<" customers to be seated"<<endl; | |
mtx_cout.unlock(); | |
//make customers seated on this table | |
mtx_tables.lock(); | |
tables[index].free_spaces -= order.number_of_customers; | |
thread t = thread (group_of_customers_on_a_table_func, order, ref(tables[index]), index); | |
mtx_tables.unlock(); | |
threads_to_be_joined.push_back(move(t)); | |
return; | |
} | |
else | |
{ | |
mtx_cout.lock(); | |
cout<<"Finding a table for customers of order #"<<order.index<<" | "<<"Relevant table was NOT found"<<endl; | |
mtx_cout.unlock(); | |
//scan tables until they get free | |
} | |
//index - here the order will be seated | |
} | |
} | |
void manage_oven(int oven_index) | |
{ | |
while(true) | |
{ | |
Oven oven = ovens.at(oven_index); | |
if(!oven.pizzas.empty()) | |
{ | |
mtx_cout.lock(); | |
cout<<"Managing Oven #"<<oven_index<<" | "<<"There are pizzas to be cooked"<<endl; | |
mtx_cout.unlock(); | |
Pizza pizza = oven.pizzas.front(); | |
oven.status = oven_status_enum::COOKING; | |
if(pizza.pizza_size == pizza_size_enum::LARGE) | |
{ | |
mtx_cout.lock(); | |
cout<<"Managing Oven #"<<oven_index<<" | "<<"Starting to cook a large pizza from order #"<<pizza.order->index<<endl; | |
mtx_cout.unlock(); | |
usleep(timestamps_large_pizza_cooking*TIMESTAMP_B); | |
mtx_cout.lock(); | |
cout<<"Managing Oven #"<<oven_index<<" | "<<"Pizza cooked"<<endl; | |
mtx_cout.unlock(); | |
oven.queue_total_time -= timestamps_large_pizza_cooking*TIMESTAMP_B; | |
pizza.status = pizza_status_enum::ready; | |
mtx_orders.lock(); | |
pizza.order->increment_large_pizzas_ready(); | |
mtx_orders.unlock(); | |
} | |
else if(pizza.pizza_size == pizza_size_enum::SMALL) | |
{ | |
mtx_cout.lock(); | |
cout<<"Managing Oven #"<<oven_index<<" | "<<"Starting to cook a small pizza from order #"<<pizza.order->index<<endl; | |
mtx_cout.unlock(); | |
usleep(timestamps_small_pizza_cooking*TIMESTAMP_B); | |
mtx_cout.lock(); | |
cout<<"Managing Oven #"<<oven_index<<" | "<<"Pizza cooked"<<endl; | |
mtx_cout.unlock(); | |
oven.queue_total_time -= timestamps_small_pizza_cooking*TIMESTAMP_B; | |
pizza.status = pizza_status_enum::ready; | |
mtx_orders.lock(); | |
pizza.order->increment_small_pizzas_ready(); | |
mtx_orders.unlock(); | |
} | |
if(pizza.order->is_order_completed()) | |
{ | |
mtx_cout.lock(); | |
cout<<"Managing Oven #"<<oven_index<<" | "<<"Pizza cooked made order completed"<<endl; | |
mtx_cout.unlock(); | |
//start looking for a table | |
//scan the tables here, or put this order in a queue of table manager | |
thread t = thread (find_relevant_table, ref(*(pizza.order))); | |
threads_to_be_joined.push_back(move(t)); | |
} | |
oven.pizzas.pop(); | |
} | |
else | |
{ | |
mtx_cout.lock(); | |
cout<<"Managing Oven #"<<oven_index<<" | "<<"NO pizzas to be cooked"<<endl; | |
mtx_cout.unlock(); | |
} | |
} | |
//gotta return some time in future | |
} | |
void launch_order(Order * order) // not sure about pointer of second para here | |
{ | |
mtx_cout.lock(); | |
cout<<"launching order #"<<order->index<<endl; | |
mtx_cout.unlock(); | |
for(int i = order->n_large_pizzas_ordered; i > 0; i--) | |
{ | |
int index = find_least_busy_oven(); | |
mtx_ovens.lock(); | |
ovens.at(index).pizzas.push(Pizza(pizza_size_enum::LARGE,order)); | |
ovens.at(index).queue_total_time += TIMESTAMPS_TO_EAT_LARGE_PIZZA; | |
mtx_ovens.unlock(); | |
} | |
for(int i = order->n_small_pizzas_ordered; i > 0; i--) | |
{ | |
int index = find_least_busy_oven(); | |
mtx_ovens.lock(); | |
ovens.at(index).pizzas.push(Pizza(pizza_size_enum::SMALL, order)); | |
ovens.at(index).queue_total_time += TIMESTAMPS_TO_EAT_SMALL_PIZZA; | |
mtx_ovens.unlock(); | |
} | |
} | |
void launch_orders() | |
{ | |
int timestamps_a_passed = 0; | |
while(!orders.empty()) | |
{ | |
usleep(TIMESTAMP_A); | |
timestamps_a_passed++; | |
while(timestamps_a_passed == orders.front().issue_time) | |
{ | |
mtx_cout.lock(); | |
cout<<"timestamps_a_passed = "<<timestamps_a_passed<<endl; | |
mtx_cout.unlock(); | |
Order order = orders.front(); | |
mtx_orders.lock(); | |
//launch an order in a separate thread now | |
launch_order(&order); | |
orders.pop(); | |
mtx_orders.unlock(); | |
} | |
mtx_cout.lock(); | |
cout<<"2000ms passed"<<endl; | |
mtx_cout.unlock(); | |
} | |
} | |
int main() | |
{ | |
tables[0] = Table(8); | |
tables[1] = Table(20); | |
tables[2] = Table(4); | |
tables[3] = Table(4); | |
tables[4] = Table(4); | |
tables[5] = Table(4); | |
tables[6] = Table(1); | |
tables[7] = Table(1); | |
tables[8] = Table(1); | |
tables[9] = Table(1); | |
tables[10] = Table(1); | |
//read the input data | |
string my_text; | |
ifstream input_file("Mission0.txt"); | |
// Use a while loop together with the getline() function to read the file line by line | |
if(getline (input_file, my_text)) | |
{ | |
if(my_text.substr(0, my_text.length()-1) == "Short simulation") | |
{ | |
problem_id = SMALL_SHOP_PROBLEM_ID; | |
n_ovens = SMALL_SHOP_N_OVENS; | |
timestamps_large_pizza_cooking = SMALL_SHOP_TIMESTAMPS_LARGE_PIZZA; | |
timestamps_small_pizza_cooking = SMALL_SHOP_TIMESTAMPS_SMALL_PIZZA; | |
} | |
else if(my_text.substr(0, my_text.length()-1) == "Long simulation") | |
{ | |
problem_id = LARGE_SHOP_PROBLEM_ID; | |
n_ovens = LARGE_SHOP_N_OVENS; | |
timestamps_large_pizza_cooking = LARGE_SHOP_TIMESTAMPS_LARGE_PIZZA; | |
timestamps_small_pizza_cooking = LARGE_SHOP_TIMESTAMPS_SMALL_PIZZA; | |
} | |
//title of the txt like "Short simulation" | |
while (getline (input_file, my_text)) { | |
// Output the text from the file | |
if(my_text != "END") | |
{ | |
string s[5], delimiter = ","; | |
int i[5]; | |
s[0] = my_text.substr(0, my_text.find(delimiter)); | |
i[0] = stoi(s[0]); | |
my_text.erase(0, my_text.find(delimiter) + delimiter.length()); | |
s[1] = my_text.substr(0, my_text.find(delimiter)); | |
i[1] = stoi(s[1]); | |
my_text.erase(0, my_text.find(delimiter) + delimiter.length()); | |
s[2] = my_text.substr(0, my_text.find(delimiter)); | |
i[2] = stoi(s[2]); | |
my_text.erase(0, my_text.find(delimiter) + delimiter.length()); | |
s[3] = my_text.substr(0, my_text.find(delimiter)); | |
i[3] = stoi(s[3]); | |
my_text.erase(0, my_text.find(delimiter) + delimiter.length()); | |
s[4] = my_text; | |
i[4] = stoi(s[4]); | |
//cout<<i[0]<<" "<<i[1]<<" "<<i[2]<<" "<<i[3]<<" "<<i[4]<<endl; | |
orders.push(Order(i[0], i[1], i[2], i[3], i[4])); //put the order in a queue | |
} | |
else | |
{ | |
break; | |
} | |
} | |
} | |
//uncomment later | |
thread threads[n_ovens]; | |
for(int i = 0; i < n_ovens; i++) | |
{ | |
ovens.push_back(Oven()); | |
threads[i] = thread(manage_oven, i); | |
} | |
input_file.close(); // Close the file | |
thread orders_launcher(launch_orders); | |
orders_launcher.join(); | |
for(int i = 0; i < n_ovens; i++) | |
{ | |
threads[i].join(); | |
} | |
for(int i = 0; i < threads_to_be_joined.size(); i++) | |
{ | |
threads_to_be_joined.at(i).join(); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment