⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ģ

📁 用于模拟交通的排队
💻
字号:
// 模拟View.cpp : implementation of the CMyView class
//

#include "stdafx.h"
#include "模拟.h"

#include "模拟Doc.h"
#include "模拟View.h"
#include <math.h>
#include <mshtml.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CMyView

IMPLEMENT_DYNCREATE(CMyView, CHtmlView)

BEGIN_MESSAGE_MAP(CMyView, CHtmlView)
	//{{AFX_MSG_MAP(CMyView)
	ON_WM_TIMER()
	ON_COMMAND(ID_MENU_PARAMETER, OnSetParameter)
	ON_COMMAND(ID_BUTTON_BEGAIN, OnButBegain)
	ON_COMMAND(ID_FILE_BEGAIN, OnFileBegain)
	ON_COMMAND(ID_FILE_STOP, OnFileStop)
	ON_COMMAND(ID_BUTTONEND, OnButtonEnd)
	//}}AFX_MSG_MAP
	// Standard printing commands
	ON_COMMAND(ID_FILE_PRINT, CHtmlView::OnFilePrint)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMyView construction/destruction

CMyView::CMyView()
{
	// TODO: add construction code here
	hasBegain=FALSE;
	hasEnd=FALSE;
	Length=500;
	Marrvt=0.5;
	Mservt=1.0;
}

CMyView::~CMyView()
{
}

BOOL CMyView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

	return CHtmlView::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
// CMyView drawing

void CMyView::OnDraw(CDC* pDC)
{
	CMyDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here
}

void CMyView::OnInitialUpdate()
{
	CHtmlView::OnInitialUpdate();

	// TODO: This code navigates to a popular spot on the web.
	//  change the code to go where you'd like.
	//Navigate2(_T("http://www.microsoft.com/visualc/"),NULL,NULL);
	LoadFromResource(IDR_HTML1);
}

/////////////////////////////////////////////////////////////////////////////
// CMyView printing


/////////////////////////////////////////////////////////////////////////////
// CMyView diagnostics

#ifdef _DEBUG
void CMyView::AssertValid() const
{
	CHtmlView::AssertValid();
}

void CMyView::Dump(CDumpContext& dc) const
{
	CHtmlView::Dump(dc);
}

CMyDoc* CMyView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMyDoc)));
	return (CMyDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CMyView message handlers
void CMyView::Init()
{
	if(hasBegain && !hasEnd)//正在运行
	{
		MessageBox("正在模拟,如需重新开始请先停止!");
		return;
	}
	hasBegain=TRUE;
	hasEnd=FALSE;
	if(Length<0){
		MessageBox("请先进行参数设置");
		return;
	}
	Tnum=0;    //当前模拟时间
	ChangeQueue_num=0;    //换队的顾客数目
	LeaveQueue_num=0;    //因为排满而离开的顾客数目
	noWait_num=2;    //没有等待就可以服务的顾客数
	wait_num=4;    //需要等待才可以接受服务的顾客数目
	leaveServer_num=0;    //享受完服务的顾客数目
	TotalWaitT=0;    //享受完服务的顾客总共等待时间
	TotalServerT=0;    //享受完服务的顾客总共接受服务的时间

	for(int i=0;i<TEL;i++)
	{
		//初始化服务台
		server[i].status=TRUE;    //处于忙状态
		server[i].begainBusyT=0;
		server[i].sumBusyT=0;
		//初始化队列
		queue[i].length=3;
		queue[i].client[0].arriveT=0;
		queue[i].client[0].serverT=0;
		queue[i].client[0].leaveT=-1;  //等于-1代表还没有发生
		queue[i].client[1].arriveT=0;
		queue[i].client[1].serverT=-1;
		queue[i].client[1].leaveT=-1;
		queue[i].client[2].arriveT=0;
		queue[i].client[2].serverT=-1;
		queue[i].client[2].leaveT=-1;
		queue[i].client[3].arriveT=-1;
		queue[i].client[3].serverT=-1;
		queue[i].client[3].leaveT=-1;
		CString str;
		str.Format("1%d",i+1);
		ShowPic(str);
		str.Format("2%d",i+1);
		ShowPic(str);
		str.Format("3%d",i+1);
		ShowPic(str);
	}

	ArrivePara=(float)(1-exp(Tinterval*-1/Marrvt));
	srand( (unsigned)time( NULL ) );
	SetTimer(1,60,0);
}
void CMyView::Stop()
{
	KillTimer(1);
	//更新画面
	for(int i=0;i<MAXLEN;i++)
	{
		for(int j=0;j<TEL;j++)
		{
			CString str;
			str.Format("%d%d",i+1,j+1);
			ShowPic(str,FALSE);
		}
	}
	hasEnd=TRUE;
}

void CMyView::OnTimer(UINT nIDEvent) 
{
	// TODO: Add your message handler code here and/or call default
	Tnum++;

	int i,j;
	int irandnum=0;
	float frandnum=0.0;

	irandnum=rand();
	frandnum=(float)irandnum/(float)RAND_MAX;
	//已经产生了一个顾客的随机数
	if(frandnum<ArrivePara)
	{
		//此时产生顾客到达事件
		Arrive();
	}
	for(i=0;i<TEL;i++)
	{
		if(queue[i].length>0)
		{
			irandnum=rand();
			frandnum=(float)irandnum/(float)RAND_MAX;
			if(frandnum<ServerPara)
			{
				//此时队列i产生顾客离去事件
				Epart(i);
			}
		}
	}
	//判断是否换队	
	for(i=0;i<TEL;i++)
	{
		for(j=i+1;j<TEL;j++)
		{
			if(queue[i].length-1>queue[j].length)
			{
				//由i换队到j
				Jockey(i,j);
			}else if(queue[j].length-1>queue[i].length)
			{
				//由j换队到i
				Jockey(j,i);
			}
		}
	}
	CMyDoc *pDoc=GetDocument();
	COleVariant var;
	//report系统中平均顾客数
	float temp=(float)(LeaveQueue_num+noWait_num+wait_num);
	var=temp*10/Tnum;
	pDoc->Report(1,var);
	//report队列中的平均顾客数
	temp=(float)(noWait_num+wait_num);
	var=temp*10/Tnum/2;
	pDoc->Report(2,var);
	//report出纳员利用率
	var=(float)TotalServerT/Tnum/2*100;
	pDoc->Report(0,var);
	if(Tnum>=Length*10){
		KillTimer(1);
		MessageBox("模拟结束");
	}
	CHtmlView::OnTimer(nIDEvent);
}
//顾客到达
void CMyView::Arrive()
{
	CMyDoc *pDoc=GetDocument();
	int i=0;
	//如果队列全满了则离去
	BOOL bFull=TRUE;
	for(i=0;i<TEL;i++)
	{
		if(queue[i].length!=MAXLEN)
		{
			bFull=FALSE;
			break;
		}
	}
	if(bFull)    //队都站满了
	{
		LeaveQueue_num++;
		//Report 因排满而离开的顾客数
		COleVariant var;
		long temp=LeaveQueue_num;
		var=temp;
		pDoc->Report(4,var);
		return;
	}
	//运行到此说明有位置可站
	//寻找最短队列
	int shortQueue=0;  //初始化,认为0队列最短
	for(i=1;i<TEL;i++)
	{
		if(queue[i].length<queue[shortQueue].length)
		{
			shortQueue=i;
		}
	}
	//此时最短队为shortQueue
	//所以排在shortQueue队
	//如果shortQueue队队长为0,顾客可以直接接受服务
	if(queue[shortQueue].length==0)
	{
		noWait_num++;
		queue[shortQueue].length=1;
		queue[shortQueue].client[0].arriveT=Tnum;  //客户到达时间
		queue[shortQueue].client[0].leaveT=-1;  //离开时间
		queue[shortQueue].client[0].serverT=Tnum;  //开始接受服务时间
		//这里用于调试
		#ifdef _DEBUG
		if(server[shortQueue].status==TRUE)
		{
			MessageBox("出错了,队长为0时,服务台也忙!");
		}
		#endif //_DEBUG
		//设置服务台的状态即开始忙的时间
		server[shortQueue].status=TRUE;
		server[shortQueue].begainBusyT=Tnum;
		//显示画面
		CString str;
		str.Format("1%d",shortQueue+1);
		ShowPic(str);
	}else{    //否则的话需要排队
		wait_num++;   //需要排队的顾客数加1
		queue[shortQueue].length++; //队长加1
		int len=queue[shortQueue].length-1;  //因为数组从0开始
		queue[shortQueue].client[len].arriveT=Tnum;  //客户到达时间
		queue[shortQueue].client[len].leaveT=-1;  //离开时间
		queue[shortQueue].client[len].serverT=-1;  //开始接受服务时间
		//显示画面
		CString str;
		str.Format("%d%d",len+1,shortQueue+1);
		ShowPic(str);
	}
}

//顾客离去
void CMyView::Epart(int nQueu)
{
	queue[nQueu].client[0].leaveT=Tnum;
	CMyDoc *pDoc=GetDocument();
	COleVariant var;
	//享受完服务的顾客数目+1
	leaveServer_num++;
	//设置享受完服务的顾客总共等待时间
	#ifdef _DEBUG
	if(queue[nQueu].client[0].serverT<0 || queue[nQueu].client[0].arriveT<0)
	{
		MessageBox("出错了,离去时开始服务时间或到达时间小于0!");
	}
	#endif //_DEBUG
	//Report 总等待时间和平均等待时间
	TotalWaitT+=queue[nQueu].client[0].serverT-queue[nQueu].client[0].arriveT;
	long temp;
	temp=TotalWaitT/10;
	var=temp;
	pDoc->Report(5,var);
	float aveWaitT=(float)TotalWaitT/(float)leaveServer_num;
	var=aveWaitT/10;
	pDoc->Report(7,var);
	//享受完服务的顾客总共接受服务的时间
	#ifdef _DEBUG
	if(queue[nQueu].client[0].serverT>queue[nQueu].client[0].leaveT)
	{
		MessageBox("出错了,开始服务时间>离开时间!");
	}
	#endif //_DEBUG
	//Report 总接受服务时间和平均接受服务时间
	TotalServerT+=queue[nQueu].client[0].leaveT-queue[nQueu].client[0].serverT;
	temp=TotalServerT/10;
	var=temp;
	pDoc->Report(6,var);
	float aveServeT=(float)TotalServerT/(float)leaveServer_num;
	var=aveServeT/10;
	pDoc->Report(8,var);
	//用于测试
	#ifdef _DEBUG
	if(queue[nQueu].length<=0)
	{
		MessageBox("出错了,离去的队列队长为0!");
	}
	#endif //_DEBUG

	//首先让队长-1
	queue[nQueu].length--;

	//用于测试
	#ifdef _DEBUG
	if(server[nQueu].status==FALSE)
	{
		MessageBox("出错了,队列有人的时候服务台状态为空闲!");
	}
	#endif //_DEBUG

	//更新服务台
	//如果离去后队长为0,则服务台处于空闲状态
	if(queue[nQueu].length==0)
	{
		//设置服务台处于空闲状态
		server[nQueu].status=FALSE;
		server[nQueu].sumBusyT+=Tnum-server[nQueu].begainBusyT;
		server[nQueu].begainBusyT=-1;
		//显示画面
		CString str;
		str.Format("%d%d",1,nQueu+1);
		ShowPic(str,FALSE);
	}else{    //根新队列,让每个顾客向前移动
		for(int i=0;i<queue[nQueu].length;i++)
		{
			queue[nQueu].client[i]=queue[nQueu].client[i+1];
		}
		//设置最前面的顾客的开始服务时间
		queue[nQueu].client[0].serverT=Tnum;
		//显示画面
		CString str;
		str.Format("%d%d",queue[nQueu].length+1,nQueu+1);//queue[nQueu].length为离去后的队长
		ShowPic(str,FALSE);
	}
}

 //顾客换队
void CMyView::Jockey(int formQueu,int toQueu)
{
	CMyDoc *pDoc=GetDocument();
	COleVariant var;
	//换队的人数加1
	ChangeQueue_num++;
	//Report换队人数
	long temp=ChangeQueue_num;
	var=temp;
	pDoc->Report(3,var);
	//离去的队队长-1
	queue[formQueu].length--;
	//到达的队队长+1
	queue[toQueu].length++;

	int len1,len2;
	//离去的顾客
	len1=queue[formQueu].length+1;
	//到达的顾客
	len2=queue[toQueu].length;
	//更新队列中的顾客属性
	queue[toQueu].client[len2]=queue[formQueu].client[len1];
	//如果len2=1,说明这个队在换队之前没人,需要根新服务台状态
	if(len2==1)
	{
		//根新服务台状态
		server[toQueu].status=TRUE;
		server[toQueu].begainBusyT=Tnum;
		//设置刚换队过来的人的开始服务时间
		queue[toQueu].client[0].serverT=Tnum;
	}
	//显示画面
	CString str;
	str.Format("%d%d",len1,formQueu+1);
	ShowPic(str,FALSE);
	str.Format("%d%d",len2,toQueu+1);
	ShowPic(str);
}

void CMyView::OnSetParameter()
{
	// TODO: Add your command handler code here
	CParaDlg m_Dlg;
	//m_Dlg.UpdateData(FALSE);
	if(m_Dlg.DoModal()==IDOK){
		Length=m_Dlg.m_total_server_Time;
		Marrvt=m_Dlg.m_ave_Arrive_Time;
		//Mservt=m_Dlg.m_ave_Server_Time;
	}
}

void CMyView::OnButBegain() 
{
	// TODO: Add your command handler code here
	Init();
}

void CMyView::OnFileBegain() 
{
	// TODO: Add your command handler code here
	Init();
}

void CMyView::OnFileStop() 
{
	// TODO: Add your command handler code here
	Stop();
}

void CMyView::OnButtonEnd() 
{
	// TODO: Add your command handler code here
	Stop();
}
void CMyView::ShowPic(CString id,BOOL isShow)
{
	IDispatch* pDisp=GetHtmlDocument();
	if(pDisp!=NULL)
	{
		IHTMLDocument2 *pHTMLDocument2;
		HRESULT hr;

		hr=pDisp->QueryInterface(IID_IHTMLDocument2,(void **)&pHTMLDocument2);
		if(hr==S_OK)
		{
			IHTMLElementCollection *pColl=NULL;
			hr= pHTMLDocument2->get_all(&pColl);

			if(hr==S_OK && pColl!=NULL)
			{
				LONG celem;
				hr=pColl->get_length(&celem);
				if(hr==S_OK)
				{
					for(int i=0;i<celem;i++)
					{
						VARIANT varIndex;
						varIndex.vt=VT_UINT;
						varIndex.lVal=i;
						VARIANT var2;
						VariantInit(&var2);
						IDispatch *pDisp;

						hr=pColl->item(varIndex,var2,&pDisp);
						if(hr==S_OK && !pDisp==NULL)
						{
							IHTMLElement *pElem;
							hr=pDisp->QueryInterface(IID_IHTMLElement,(void**)&pElem);
							if(hr==S_OK && !pElem==NULL)
							{
								BSTR bstr;
								pElem->get_id(&bstr);
								CString str=bstr;
								if(str==id){
									IHTMLTableCell *pCellElem;
									hr=pDisp->QueryInterface(IID_IHTMLTableCell,(void **)&pCellElem);
									if(hr==S_OK && pCellElem!=NULL){
										if(isShow)
										{
											COleVariant var("#0000ff");
											//var.bstrVal="#0000ff";
											pCellElem->put_bgColor(var);
										}else{
											COleVariant var("#ffffff");
											pCellElem->put_bgColor(var);
										}
										pCellElem->Release();
										pCellElem=NULL;
									}
								}
								pElem->Release();
								pElem=NULL;
							}
							pDisp->Release();
						}
					}
				}
				pColl->Release();
			}
			pHTMLDocument2->Release();
		}
		pDisp->Release();
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -