Skip to content

Instantly share code, notes, and snippets.

@iamsardorbek
Created April 20, 2021 20:27
Show Gist options
  • Save iamsardorbek/051419f540d92e5006284e7be3370199 to your computer and use it in GitHub Desktop.
Save iamsardorbek/051419f540d92e5006284e7be3370199 to your computer and use it in GitHub Desktop.
#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