提交 a6cc989c 编辑于 作者: yilin wang's avatar yilin wang
浏览文件

Upload New File

上级 1d57c919
#ifndef SIMULATION_CLASS
#define SIMULATION_CLASS
#include <iostream>
#include <iomanip>
#pragma hdrstop
#include "random.h" // include random number generator
using namespace std;
// specifies the two kinds of events
enum EventType {arrival, departure};
class Event
{
private:
// members that identify both customer and teller, as
// well as maintain information on time of the event,
// the event type, the length of service required by
// the customer, and the amount of time customer is
// forced to wait for service
int time;
EventType etype;
int customerID; // customers numbered 1, 2, 3,...
int tellerID; // tellers numbered 1, 2, 3,...
int waittime;
int servicetime;
int customertype; //VIP(1) or 普通顾客(0)
public:
// constructors
Event(void);
Event(int t,EventType et,int cn,int tn,
int wt,int st,int vip);
// methods to retrieve private data
int GetTime(void) const;
EventType GetEventType(void) const;
int GetCustomerID(void) const;
int GetTellerID(void) const;
int GetWaitTime(void) const;
int GetServiceTime(void) const;
int GetCustomerType(void) const; //
};
// default constructor - data filled by assignment later
Event::Event(void)
{}
// constructor that initializes all data members of the event
Event::Event(int t,EventType et,int cn,int tn,
int wt,int st,int vip):
time(t),etype(et),customerID(cn),tellerID(tn),
waittime(wt),servicetime(st),customertype(vip)
{}
// return the time the event occurs
int Event::GetTime(void) const
{
return time;
}
// return the type of event (arrival, departure)
EventType Event::GetEventType(void) const
{
return etype;
}
// return the customer number
int Event::GetCustomerID(void) const
{
return customerID;
}
// return the teller number
int Event::GetTellerID(void) const
{
return tellerID;
}
// return the time the customer waits for service
int Event::GetWaitTime(void) const
{
return waittime;
}
// return the amount of teller time needed by customer
int Event::GetServiceTime(void) const
{
return servicetime;
}
int Event::GetCustomerType(void) const
{
return customertype;
}
// compare two Event objects using the time at
// which the events occur. needed for the priority queue
int operator< (Event e1, Event e2)
{
if(e1.GetEventType()){ //departure event 优先队列
return e1.GetTime()<e2.GetTime();
}
//arrival event 优先队列
if(e1.GetCustomerType()!=e2.GetCustomerType())return e1.GetCustomerType() > e2.GetCustomerType(); //VIP顾客优先于普通顾客
return e1.GetTime() < e2.GetTime();
}
typedef Event DataType; // elements are Event objects
#include "apqueue.h"
// Structure for Teller Info
struct TellerStats
{
int finishService; // when teller available
int totalCustomerCount; // total of customers serviced
int totalCustomerWait; // total customer waiting time
int totalService; // total time servicing customers
};
class Simulation
{
private:
// data used to run the simulation
int simulationLength; // simulation length
int numTellers; // number of tellers
int nextCustomer; // next customer ID
int arrivalLow, arrivalHigh; // next arrival range
int serviceLow, serviceHigh; // service range
int vipfrequency; //vip顾客频率 (每vipfrequency个顾客中出现一个vip顾客) 建议设为2 vip顾客和普通顾客可以较多穿插
TellerStats tstat[11]; // max 10 tellers
PQueue pqarr; // arrival事件
PQueue pqdep; // departure事件
RandomNumber rnd; // use for arrival
// and service times
// private methods used by RunSimulation
int NextArrivalTime(void);
int NextVIP(void); //下一个顾客是不是VIP
int GetServiceTime(void);
int NextAvailableTeller(void);
public:
// constructor
Simulation(void);
void RunSimulation(void); // execute study
void PrintSimulationResults(void); // print stats
};
// constructor initializes simulation data and prompts client
// for simulation parameters
Simulation::Simulation(void)
{
int i;
Event firstevent;
// Initialize Teller Information Parameters
for(i = 1; i <= 10; i++)
{
tstat[i].finishService = 0;
tstat[i].totalService = 0;
tstat[i].totalCustomerWait = 0;
tstat[i].totalCustomerCount = 0;
}
nextCustomer = 1;
// reads client input for the study
cout << "Enter the simulation time in minutes: ";
cin >> simulationLength;
cout << "Enter the number of bank tellers: ";
cin >> numTellers;
cout << "Enter the range of arrival times in minutes: ";
cin >> arrivalLow >> arrivalHigh;
cout << "Enter the range of service times in minutes: ";
cin >> serviceLow >> serviceHigh;
cout <<"Enter the frequency of vip cumstomers: ";
cin >> vipfrequency;
// generate first arrival event
// teller#/waittime/servicetime not used for arrival
Event e=Event(0,arrival,1,0,0,0,NextVIP());
pqarr.PQInsert(e);
cout << "Time: " << setw(2) << e.GetTime()
<< " " << "arrival of" <<(e.GetCustomerType()?" VIP ":" ")
<<"customer " << e.GetCustomerID() << endl;
}
// determine random time of next arrival
int Simulation::NextArrivalTime(void)
{
return arrivalLow+rnd.Random(arrivalHigh-arrivalLow+1);
}
// determine random time for customer service
int Simulation::GetServiceTime(void)
{
return serviceLow+rnd.Random(serviceHigh-serviceLow+1);
}
int Simulation::NextVIP(void)
{
return rnd.Random(vipfrequency)==0?1:0;
}
// return first available teller
int Simulation::NextAvailableTeller(void)
{
// initially assume all tellers finish at closing time
int minfinish = simulationLength;
// assign random teller to customer who arrives
// before closing but obtains service after closing
int idx = rnd.Random(numTellers) + 1; //尽量保证多个teller可用时,随机选择一个teller
int dir=rnd.Random(2); //dir为0时 teller从左往右遍历; dir为1时 teller从右往左遍历
int ans=idx; //ans记录答案 即finishservice最小的teller
// find teller who is free first
if(dir){
for (int i = 1; i <= numTellers; i++){
int now=(i+idx)%numTellers+1; //i对应的实际上的teller
if (tstat[now].finishService < minfinish)
{
minfinish = tstat[now].finishService;
ans = now;
}
}
}
else{
for (int i = numTellers; i >=1 ; i--){
int now=(i+idx)%numTellers+1; //i对应的实际上的teller
if (tstat[now].finishService < minfinish)
{
minfinish = tstat[now].finishService;
ans = now;
}
}
}
return ans;
}
// implements the simulation
void Simulation::RunSimulation(void)
{
Event e, newevent;
int nexttime = NextArrivalTime();
int tellerID;
int servicetime;
int waittime;
int isVIP;
for(int t=0;t<=simulationLength;++t){
if(t==nexttime){
++nextCustomer;
newevent = Event(t, arrival, nextCustomer, 0, 0, 0, NextVIP());
cout << "Time: " << setw(2) << newevent.GetTime()
<< " " << "arrival of" <<(newevent.GetCustomerType()?" VIP ":" ")
<<"customer " << newevent.GetCustomerID() << endl;
pqarr.PQInsert(newevent);
nexttime += NextArrivalTime();
}
while(!pqdep.PQEmpty()){
e=pqdep.PQDelete();
if(e.GetTime()>t){
pqdep.PQInsert(e);
break;
}
cout << "Time: " << setw(2) << e.GetTime()
<< " " << "departure of" <<(e.GetCustomerType()?" VIP":" ")
<<" customer " << e.GetCustomerID() << endl;
cout << " Teller " << e.GetTellerID()
<< " Wait " << e.GetWaitTime()
<< " Service " << e.GetServiceTime()
<< endl;
}
while(!pqarr.PQEmpty()){
e=pqarr.PQDelete();
tellerID = NextAvailableTeller();
//cout<<e.GetTime()<<" dawafaef "<<tstat[tellerID].finishService<<endl;
if(t >= tstat[tellerID].finishService){ //是t
servicetime = GetServiceTime();
waittime = max(tstat[tellerID].finishService - e.GetTime(), 0); //
tstat[tellerID].totalCustomerWait += waittime;
tstat[tellerID].totalCustomerCount++;
tstat[tellerID].totalService += servicetime;
tstat[tellerID].finishService = servicetime + max(e.GetTime(), tstat[tellerID].finishService); //
// create a departure object and put in the queue
newevent = Event(tstat[tellerID].finishService,
departure,e.GetCustomerID(),tellerID,
waittime,servicetime,e.GetCustomerType());
pqdep.PQInsert(newevent);
}
else {
pqarr.PQInsert(e);break;
}
}
}
while(!pqarr.PQEmpty()){
e=pqarr.PQDelete();
cout<<"Time has exceeded the simulation time!\nIt's sorry to tell"
<<(e.GetCustomerType()?" VIP ":" ")<<"cumstomer "<<e.GetCustomerID()
<<" to leave!\n";
}
while(!pqdep.PQEmpty()){
e=pqdep.PQDelete();
cout << "Time: " << setw(2) << e.GetTime()
<< " " << "departure of" <<(e.GetCustomerType()?" VIP":" ")
<<" customer " << e.GetCustomerID() << endl;
cout << " Teller " << e.GetTellerID()
<< " Wait " << e.GetWaitTime()
<< " Service " << e.GetServiceTime()
<< endl;
}
// adjust simulation to account for overtime by tellers
simulationLength = (e.GetTime() <= simulationLength) ? simulationLength : e.GetTime();
}
// summarize the simulation results
void Simulation::PrintSimulationResults(void)
{
int cumCustomers = 0, cumWait = 0, i;
int avgCustWait, tellerWorkPercent;
float tellerWork;
for (i = 1; i <= numTellers; i++)
{
cumCustomers += tstat[i].totalCustomerCount;
cumWait += tstat[i].totalCustomerWait;
}
cout << endl;
cout << "******** Simulation Summary ********" << endl;
cout << "Simulation of " << simulationLength
<< " minutes" << endl;
cout << " No. of Customers: " << cumCustomers << endl;
cout << " Average Customer Wait: ";
avgCustWait = int(float(cumWait)/cumCustomers + 0.5);
cout << avgCustWait << " minutes" << endl;
for(i=1;i <= numTellers;i++)
{
cout << " Teller #" << i << " Working: ";
// display percent rounded to nearest integer value
tellerWork = float(tstat[i].totalService)/simulationLength;
tellerWorkPercent =int( tellerWork * 100.0 + 0.5);
cout << tellerWorkPercent <<"%\n";
}
}
#endif // SIMULATION_CLASS
支持 Markdown
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册