#include "barbecue.h"
#include <iostream>
void barbecue::add_guest(int arrival)
{
guest* gst = new guest(this, arrival);
_schedule_table.push(gst);
}
void barbecue::serve_guest(guest* gst)
{
_schedule_table.push(gst);
}
void barbecue::schedule()
{
while (!_schedule_table.empty())
{
guest* gst = _schedule_table.top();
_schedule_table.pop();
//根据客人的当前状态,进行服务
//1.客人在烧烤完毕后,进入FINISHED状态
//释放一个烤架,将客人请至用餐区
if (gst->_current_state == FINISHED)
{
_grill->release(gst->_res_idx);
_dining_area.push_back(gst);
std::cout << gst->_timestamp << " finished" << std::endl;
}
//2.客人在用完一次吧台后,进入下一状态;烧烤店释放一个吧台
else if (gst->_current_state == FREEBAR)
{
_bar->release(gst->_res_idx);
gst->moveto(-1, nextschedule());
}
//3.客人在等待吧台,如果有可用的吧台,则客人获取资源,并转换状态
//否则,客人的时间戳修改为下一个调度时间,以期待最近一次调度时间有机会获取资源
else if (gst->_current_state == WAITING4BAR)
{
int bar_idx = _bar->apply(gst->_timestamp + 10);
gst->moveto(bar_idx, _bar->min());
}
else if (gst->_current_state == WAITING4GRILL)
{
int grill_idx = _grill->apply(gst->_timestamp + 180);
gst->moveto(grill_idx, _grill->min());
}
}
}
void barbecue::statistics()
{
int totaltime4bar = 0;
int totaltime4grill = 0;
int count = 0;
for (std::list<guest*>::iterator iter = _dining_area.begin(); iter != _dining_area.end(); iter++)
{
count++;
totaltime4bar += (*iter)->_time4bar;
totaltime4grill += (*iter)->_time4grill;
}
double average4bar = totaltime4bar / 1.0 / count;
double average4grill = totaltime4grill / 1.0 / count;
std::cout << "平均等待吧台的时间: " << average4bar << std::endl;
std::cout << "平均等待烤架的时间: " << average4grill << std::endl;
}
//下一个最近的调度时间
int barbecue::nextschedule()
{
if (!_schedule_table.empty())
{
return _schedule_table.top()->_timestamp;
}
return LONG_MAX;
}
bool barbecue::use_one_bar()
{
if (_bar_num > 0)
{
_bar_num--;
return true;
}
return false;
}
bool barbecue::use_one_grill()
{
if (_grill_num > 0)
{
_grill_num--;
return true;
}
return false;
}
void barbecue::free_one_bar()
{
_bar_num++;
}
void barbecue::free_one_grill()
{
_grill_num++;
}
void guest::moveto(int res_idx, int newtime)
{
switch (_current_state)
{
case FREEBAR:
//获取食物未到5份,则继续申请吧台,添加到烧烤店的服务队列中
if (_food_num < 5)
{
_time_in_current_state = 0;
_current_state = WAITING4BAR;
_barbecue->serve_guest(this);
}
//获取完食物,申请烤架进行烧烤
else
{
_current_state = WAITING4GRILL;
_time_in_current_state = 0;
_barbecue->serve_guest(this);
}
break;
case WAITING4BAR:
//获取到资源,WAITING4BAR=>USINGBAR=>FREEBAR
if (res_idx != -1)
{
_time4bar += _time_in_current_state;
_timestamp += 10;
_current_state = FREEBAR;
_time_in_current_state = 0;
_res_idx = res_idx;
_food_num++;
_barbecue->serve_guest(this);
}
else
{
_time_in_current_state += newtime - _timestamp;
_timestamp = newtime;
_barbecue->serve_guest(this);
}
break;
case WAITING4GRILL:
//获取到资源,WAITING4GRILL=>USINGGRILL=>FINISHED
if (res_idx != -1)
{
_time4grill += _time_in_current_state;
_timestamp += 180;
_current_state = FINISHED;
_time_in_current_state = 0;
_res_idx = res_idx;
_barbecue->serve_guest(this);
}
else
{
_time_in_current_state += newtime - _timestamp;
_timestamp = newtime;
_barbecue->serve_guest(this);
}
break;
}
}
#ifndef __BARBECUE_H__
#define __BARBECUE_H__
#include <queue>
#include <list>
//客人状态
enum guest_state
{
FINISHED,
FREEBAR,
USINGBAR,
USINGGRILL,
WAITING4BAR,
WAITING4GRILL
};
class barbecue;
//资源类
//向用户提供获取资源,释放资源接口
class resource
{
public:
resource(int size)
{
_resources = new int[size];
for (int i = 0; i < size; i++)
_resources[i] = LONG_MAX;
_size = size;
_minValue = LONG_MAX;
}
~resource()
{
delete [] _resources;
}
public:
//申请资源,并提供释放资源的时间,成功申请返回bar的编号,否则返回-1
int apply(int time)
{
for (int i = 0; i < _size; i++)
if (_resources[i] == LONG_MAX)
{
_resources[i] = time;
_minValue = _minValue > time ? time : _minValue;
return i;
}
return -1;
}
void release(int idx)
{
_resources[idx] = LONG_MAX;
_minValue = LONG_MAX;
for (int i = 0; i < _size; i++)
{
_minValue = _minValue > _resources[i] ? _resources[i] : _minValue;
}
}
//在_bars数组中储存bar的释放时间,getMin返回最近一次吧台释放时间
int min()
{
return _minValue;
}
private:
int* _resources;
int _size;
int _minValue;
};
//每一个客人有以下信息:
//1.当前状态
//2.当前状态的维持时间
//3.累计等待吧台时间
//4.累计等待烤架时间
//5.进入烧烤店的时间
//6.时间戳,记录被招待时的时间
class guest
{
public:
guest(barbecue* bbq, int arrival)
{
_current_state = WAITING4BAR;
_time_in_current_state = 0;
_time4bar = _time4grill = 0;
_timestamp = _arrival = arrival;
_barbecue = bbq;
_food_num = 0;
_res_idx = -1;
}
public:
friend class barbecue;
bool finished() { return _current_state == FINISHED; }
void moveto(int res_idx, int newtime);
private:
barbecue* _barbecue;
guest_state _current_state;
int _time_in_current_state;
int _food_num; //当前获取了几份食物
int _time4bar;
int _time4grill;
int _arrival;
int _timestamp;
int _res_idx; //当前获取的资源编号
};
class barbecue
{
public:
//初始化20个吧台,8个烤架,时间戳为0
barbecue()
{
_bar_num = 20;
_bar = new resource(20);
_grill = new resource(8);
_grill_num = 8;
}
~barbecue()
{
for (std::list<guest*>::iterator iter = _dining_area.begin(); iter != _dining_area.end(); iter++)
{
delete (*iter);
}
while (!_schedule_table.empty())
{
guest* gst = _schedule_table.top();
_schedule_table.pop();
delete gst;
}
delete _bar;
delete _grill;
}
public:
//添加客人
void add_guest(int arrival);
//服务客人
void serve_guest(guest* gst);
//对先前添加的客人,进行服务,直到客人都烧烤完
void schedule();
void statistics();
private:
//释放烤架
void free_one_grill();
//释放吧台
void free_one_bar();
//申请使用烤架
bool use_one_grill();
//申请使用吧台
bool use_one_bar();
//下一个最近的调度时间
int nextschedule();
private:
struct cmp
{
bool operator()(const guest* a, const guest* b)
{
if (a->_timestamp == b->_timestamp) return a->_current_state > b->_current_state;
return a->_timestamp > b->_timestamp;
}
};
std::priority_queue<guest*, std::vector<guest*>, cmp> _schedule_table;
std::list<guest*> _dining_area;
int _grill_num;
resource* _grill;
resource* _bar;
int _bar_num;
};
#endif