www.pudn.com > Elevators.rar > Elevator.cpp


//## begin module%1.3%.codegen_version preserve=yes 
//   Read the documentation to learn more about C++ code generator 
//   versioning. 
//## end module%1.3%.codegen_version 
 
//## begin module%3C12090901FE.cm preserve=no 
//	  %X% %Q% %Z% %W% 
//## end module%3C12090901FE.cm 
 
//## begin module%3C12090901FE.cp preserve=no 
//## end module%3C12090901FE.cp 
 
//## Module: Elevator%3C12090901FE; Package body 
//## Subsystem:  
//## Source file: D:\Program\OOP\Elevators\SourceCode\Elevator.cpp 
 
//## begin module%3C12090901FE.additionalIncludes preserve=no 
//## end module%3C12090901FE.additionalIncludes 
 
//## begin module%3C12090901FE.includes preserve=yes 
#include "stdafx.h" 
#include "Monitor.h" 
#include "Floor.h" 
//## end module%3C12090901FE.includes 
 
// Elevator 
#include "Elevator.h" 
 
//## begin module%3C12090901FE.declarations preserve=no 
//## end module%3C12090901FE.declarations 
 
//## begin module%3C12090901FE.additionalDeclarations preserve=yes 
//## end module%3C12090901FE.additionalDeclarations 
 
 
// Class CElevator  
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
CElevator::CElevator() 
  //## begin CElevator::CElevator%3C1206FF0294_const.hasinit preserve=no 
      : m_enType(ALL), 
        m_iPassengers(0), 
        m_enStatus(WAIT), 
        m_enDirection(DOWN), 
        m_enDoorState(CLOSED), 
        m_lTimer(0), 
        m_lTotalRun(0), 
        m_lTotalIdle(0) 
  //## end CElevator::CElevator%3C1206FF0294_const.hasinit 
  //## begin CElevator::CElevator%3C1206FF0294_const.initialization preserve=yes 
  //## end CElevator::CElevator%3C1206FF0294_const.initialization 
{ 
  //## begin CElevator::CElevator%3C1206FF0294_const.body preserve=yes 
  //## end CElevator::CElevator%3C1206FF0294_const.body 
} 
 
CElevator::CElevator(const CElevator &right) 
  //## begin CElevator::CElevator%3C1206FF0294_copy.hasinit preserve=no 
      : m_enType(ALL), 
        m_iPassengers(0), 
        m_enStatus(WAIT), 
        m_enDirection(DOWN), 
        m_enDoorState(CLOSED), 
        m_lTimer(0), 
        m_lTotalRun(0), 
        m_lTotalIdle(0) 
  //## end CElevator::CElevator%3C1206FF0294_copy.hasinit 
  //## begin CElevator::CElevator%3C1206FF0294_copy.initialization preserve=yes 
  //## end CElevator::CElevator%3C1206FF0294_copy.initialization 
{ 
  //## begin CElevator::CElevator%3C1206FF0294_copy.body preserve=yes 
  //## end CElevator::CElevator%3C1206FF0294_copy.body 
} 
 
 
CElevator::~CElevator() 
{ 
  //## begin CElevator::~CElevator%3C1206FF0294_dest.body preserve=yes 
	delete m_pltPassenger; 
  //## end CElevator::~CElevator%3C1206FF0294_dest.body 
} 
 
 
CElevator & CElevator::operator=(const CElevator &right) 
{ 
  //## begin CElevator::operator=%3C1206FF0294_assign.body preserve=yes 
	return *this; 
  //## end CElevator::operator=%3C1206FF0294_assign.body 
} 
 
 
int CElevator::operator==(const CElevator &right) const 
{ 
  //## begin CElevator::operator==%3C1206FF0294_eq.body preserve=yes 
	return 0; 
  //## end CElevator::operator==%3C1206FF0294_eq.body 
} 
 
int CElevator::operator!=(const CElevator &right) const 
{ 
  //## begin CElevator::operator!=%3C1206FF0294_neq.body preserve=yes 
	return 0; 
  //## end CElevator::operator!=%3C1206FF0294_neq.body 
} 
 
 
 
//## Other Operations (implementation) 
bool CElevator::Reachable (int iFloor) 
{ 
  //## begin CElevator::Reachable%3C120D2002D0.body preserve=yes 
// 根据电梯的运行规则判断能否到达某一层 
	if(iFloor>40||iFloor<1) return false; 
	if(iFloor==1) return true; 
	switch(m_enType) 
	{ 
	//第一种类型,每层都可达. 
	case ALL:		return true;break; 
	//第二种类型,除一层外,只能到25~40. 
	case UPPART:	if(iFloor<=40 && iFloor>=25) return true; 
					else return false; 
					break; 
	//第三种类型,只能到1~25; 
	case DOWNPART:	if(iFloor>0 && iFloor<=25) return true; 
					else return false; 
					break; 
	//第四种类型,1,2~40中的偶数层. 
	case EVENS:		if(iFloor%2==0) return true; 
					else return false; 
					break; 
	//第五种类型,1~40中的奇数层. 
	case ODDS:		if(iFloor%2==1) return true; 
					else return false; 
	default:		TRACE("Wrong requried floor!\n"); 
					return false; 
					break; 
 
	} 
	return false; 
  //## end CElevator::Reachable%3C120D2002D0.body 
} 
 
bool CElevator::IsOverloading () 
{ 
  //## begin CElevator::IsOverloading%3C120D83035C.body preserve=yes 
// 电梯是否超载 
	if(m_pltPassenger->size()>=m_iCapacity) 
		return true; 
	else  
		return false; 
  //## end CElevator::IsOverloading%3C120D83035C.body 
} 
 
void CElevator::Manager () 
{ 
  //## begin CElevator::Manager%3C1212D301AE.body preserve=yes 
//电梯自己的管理器,对自己状态的转换控制. 
	int ret; 
	switch(m_enStatus){ 
	case IDLE: //电梯的空闲状态 
		m_lTotalIdle++; 
		m_bFinished = false; 
		if(m_ltMessages.empty())  
		{ 
			SetStatus(IDLE); 
			SetDirection(NONE); 
		} 
		else  
		{ 
			//消息队列不为空,检查是否要停. 
			if(StopOrNot()) Stop(); 
			//否则运行. 
			else Start(); 
		} 
		break; 
	case RUN: 
		m_bFinished = false; 
		m_lTotalRun++; 
		m_iSpeed--; 
		//速度控制电梯的位置. 
		if(!m_iSpeed) 
		{ 
			if(m_enDirection==UP) m_iLocation++; 
			else m_iLocation--; 
			m_iSpeed = m_pMonitor->m_S; 
			if(StopOrNot()) Stop(); 
		} 
		break; 
	case WAIT: 
		m_lTotalWait++; 
		m_lTotalRun++; 
		//当电梯处于等待状态的时候,我们认为他仍在工作 
		//先下后上 
		if(!--m_iPassUpDown) 
		{ 
			if(!PassengerOut()) 
			{ 
				ret = PassengerIn(); 
				if(ret!=1) m_bFinished = true; 
			} 
			m_iPassUpDown = m_pMonitor->m_T; 
		} 
		if(m_bFinished) 
		{ 
			//在这里加入由于满载而没有满足的乘客的处理 
			if(ret==2) 
			{ 
				if(!m_ltWaitMsg.empty()) Overloaded(); 
			} 
			if(m_ltMessages.empty())  
			{ 
				SetStatus(IDLE); 
				SetDirection(NONE); 
			} 
			else Start(); 
		} 
		break; 
	default:  
		break; 
	} 
  //## end CElevator::Manager%3C1212D301AE.body 
} 
 
void CElevator::Start () 
{ 
  //## begin CElevator::Start%3C1213200366.body preserve=yes 
	//电梯的启动 
	SetStatus(RUN); 
	//判断运行方向. 
	JudgeDirection(); 
  //## end CElevator::Start%3C1213200366.body 
} 
 
void CElevator::Stop () 
{ 
  //## begin CElevator::Stop%3C12133B02DA.body preserve=yes 
	//m_enDirection = STOP; 
// 电梯的停止 
	SetStatus(WAIT); 
//计算一次在电梯外楼层内等待的乘客消息队列 
	CMessage* temp; 
	CMsgList::iterator it; 
	if(!m_ltWaitMsg.empty()) m_ltWaitMsg.clear(); 
	//寻找在该楼层中有上梯请求的消息. 
	for(it = m_ltMessages.begin();it!=m_ltMessages.end();it++) 
	{ 
		temp = *it; 
		if(temp->OriFloor ==m_iLocation) 
			m_ltWaitMsg.push_back(temp); 
	} 
  //## end CElevator::Stop%3C12133B02DA.body 
} 
 
bool CElevator::StopOrNot () 
{ 
  //## begin CElevator::StopOrNot%3C130785023A.body preserve=yes 
//判断电梯是否要在某一层电梯停止 
	if(m_iLocation<=1||m_iLocation>=40) 
		ChangeDirection(); 
	if(!Reachable(m_iLocation)) return false; 
	CMessage* tmp; 
	CMsgList::iterator it; 
	CPassengerList::iterator pit; 
	CPassenger* ptmp; 
//检查乘客链表中有无要下的乘客 
	for(pit = m_pltPassenger->begin(); pit!= m_pltPassenger->end(); pit++) 
	{ 
		ptmp = *pit; 
		if(ptmp->GetObjFloor()==m_iLocation) 
		{ 
			return true; 
		} 
	} 
//检查消息队列中有无要上的乘客 
	for(it = m_ltMessages.begin(); it!= m_ltMessages.end(); it++) 
	{ 
		tmp = *it; 
		if(tmp->OriFloor==m_iLocation) 
		{ 
			ptmp = m_pltPassenger->GetPassengerByPID(tmp->PID); 
			if(ptmp==NULL)	return true; 
		} 
	} 
	return false; 
  //## end CElevator::StopOrNot%3C130785023A.body 
} 
 
 
 
void CElevator::AddMsg (CMessage* msg) 
{ 
  //## begin CElevator::AddMsg%3C13218501B8.body preserve=yes 
	//系统组织好消息后就要添加到选定电梯的消息队列中去. 
	if(m_ltMessages.size()>m_ltMessages.max_size())  
	{ 
		TRACE("Over max_size : %d\n",m_ltMessages.max_size()); 
	} 
	m_ltMessages.insert(m_ltMessages.end(),msg); 
  //## end CElevator::AddMsg%3C13218501B8.body 
} 
 
 
// Additional Declarations 
  //## begin CElevator%3C1206FF0294.declarations preserve=yes 
CElevator::CElevator(ETYPE type,int id,int speed,int capacity,int passupdown) 
{ 
	m_enType = type; 
	m_iEID = id; 
	m_iSpeed = speed; 
 
	while(true)  
	{ 
		int floor = Random(40,1); 
		if(Reachable(floor)) 
		{ 
			m_iLocation = floor; 
			break; 
		} 
	} 
	m_iCapacity = capacity; 
	m_iPassUpDown = passupdown; 
	m_iPassengers= 0; 
    m_enStatus=IDLE; 
    m_enDirection = DOWN; 
    m_enDoorState=CLOSED; 
    m_lTimer=0; 
    m_lTotalRun= 0; 
    m_lTotalIdle=0; 
	m_lTotalWait=0; 
	m_pltPassenger = new CPassengerList(); 
	m_bFinished = false; 
} 
 
void CElevator::OpenDoor() 
{ 
	m_enDoorState = OPEN; 
} 
void CElevator::CloseDoor() 
{ 
	m_enDoorState = CLOSED; 
} 
CMonitor* CElevator::GetMonitor() 
{ 
	return m_pMonitor; 
} 
 
CFloor* CElevator::GetFloor(int floor) 
{ 
	ASSERT(m_pMonitor!=NULL); 
	return m_pMonitor->GetFloor(floor); 
} 
CPassengerList* CElevator::GetLtPassenger() 
{ 
	return m_pltPassenger; 
} 
int CElevator::GetLocation() 
{ 
	return m_iLocation; 
} 
long CElevator::GetTotalRun() 
{ 
	//获取电梯运行时间. 
	return m_lTotalRun; 
} 
long CElevator::GetTotalIdle() 
{ 
	//获取电梯空闲时间. 
	return m_lTotalIdle; 
} 
ESTATUS CElevator::GetStatus() 
{ 
	return m_enStatus; 
}  
EDIRECTION CElevator::GetDirection() 
{ 
	return m_enDirection; 
} 
int CElevator::PassengerIn () 
{ 
  //## begin CElevator::PassengerIn%3BFB3ACB0050.body preserve=yes 
// 处理乘客上电梯 
	CPassengerList* pLst; 
	CPassenger* tmp; 
	CMessage* temp; 
	CFloor* floor; 
	floor = GetFloor(m_iLocation); 
	pLst = floor->m_pltFPassengers; 
//等待消息队列是否为空 
	if(m_ltWaitMsg.empty()) return 3; 
//电梯中的乘客是否超载 
	if(m_pltPassenger->size() < m_iCapacity) 
	{ 
		if(pLst->empty()) return 3;  
		// 取得等待消息队列中的第一个消息. 
		temp = m_ltWaitMsg.front(); 
		//从楼层乘客链表中找到该乘客. 
		tmp = pLst->GetPassengerByPID(temp->PID); 
		//ASSERT(tmp); 
		if(tmp!=NULL) 
		{ 
			//找到一个乘客要上该电梯. 
			//加入到电梯内部乘客链表中. 
			m_pltPassenger->push_back(tmp); 
			//从楼层中去掉 
			pLst->remove(tmp); 
			//结束该消息 
			m_ltWaitMsg.pop_front(); 
			//改变该乘客状态 
			tmp->SetStatus(INLIFT); 
		} 
		else m_ltWaitMsg.pop_front(); 
		if(m_ltWaitMsg.empty()) return 3; 
		return 1; 
	} 
	return 2;//电梯满 
  //## end CElevator::PassengerIn%3BFB3ACB0050.body 
} 
int CElevator::PassengerOut () 
{ 
  //## begin CElevator::PassengerOut%3BFB3C160226.body preserve=yes 
// 处理乘客下电梯. 
	CPassengerList::iterator it; 
	CPassenger* tmp; 
	CFloor* floor; 
	floor = GetFloor(m_iLocation); 
	for(it = m_pltPassenger->begin();it!=m_pltPassenger->end();it++) 
	{ 
		tmp = *it; 
		if(tmp->GetObjFloor() == m_iLocation) 
		{ 
			//找到了一个要在该层下梯的乘客. 
			//把它加入到该楼层乘客队列中. 
			floor->m_pltFPassengers->push_back(tmp); 
			//从乘客链表中去掉该乘客. 
			m_pltPassenger->remove(tmp); 
			//改变该乘客的当前楼层. 
			tmp->SetFloor(m_iLocation); 
			if(m_ltMessages.RemoveByPID(tmp->GetPID())) 
			{ 
				//从消息队列中去掉该乘客后. 
				//乘客执行自己的结束一次乘坐操作. 
				tmp->FinishOneRide(); 
				return 1; 
			} 
			else 
			{ 
				TRACE("该乘客P%d并没有在消息队列中!\n",tmp->GetPID()); 
				return 1; //暂时不作处理 
			} 
		} 
	} 
	return 0; //所有要下的乘客离开电梯 
 
  //## end CElevator::PassengerOut%3BFB3C160226.body 
} 
void CElevator::ChangeDirection() 
{ 
	//改变电梯当前运行方向. 
	if(m_enDirection==UP) m_enDirection = DOWN; 
	else 
	{ 
		if(m_enDirection==DOWN) m_enDirection = UP; 
	} 
} 
  //## end CElevator%3C1206FF0294.declarations 
 
//## begin module%3C12090901FE.epilog preserve=yes 
//## end module%3C12090901FE.epilog 
 
void CElevator::SetStatus(ESTATUS status) 
{ 
	//获取电梯状态. 
	m_enStatus = status; 
 
} 
void CElevator::Overloaded() 
{ 
//当电梯出现超载的情况,电梯作出的处理.	 
	CPassenger* temp; 
	CMessage* tmp; 
	CFloor* floor; 
	CPassengerList* pLst; 
	floor = GetFloor(m_iLocation); 
	pLst = floor->m_pltFPassengers; 
	while(1) 
	{ 
		//取出楼层中等待该电梯的第一个消息. 
		tmp = m_ltWaitMsg.front(); 
		//在楼层乘客链表中找到该乘客. 
		temp = pLst->GetPassengerByPID(tmp->PID); 
		if(temp!=NULL) 
		{ 
			//如果该乘客存在的话,改变他的状态为没有满足. 
			temp->SetStatus(NOTSERVED); 
			//从消息队列中去掉该消息. 
			m_ltMessages.remove(tmp); 
			//从等待消息队列中去掉该消息. 
			m_ltWaitMsg.pop_front(); 
			//如果没有别的等待消息,退出. 
			if(m_ltWaitMsg.empty()) break; 
		} 
		else 
		{ 
			//如果不存在,直接去掉该消息. 
			m_ltWaitMsg.pop_front(); 
			if(m_ltWaitMsg.empty()) break; 
		} 
	} 
} 
 
void CElevator::JudgeDirection() 
{ 
//电梯在每次启动之前都要判断自己的方向.	 
	CMessage * tmp; 
	CMsgList::iterator it; 
	CPassengerList::iterator pit; 
	CPassenger * ptmp; 
	CFloor* floor; 
	CPassengerList* pLst; 
	TRACE("Check direction!\n"); 
	switch(m_enDirection) 
	{ 
	case UP: 
		for(it = m_ltMessages.begin(); it!= m_ltMessages.end(); it++) 
		{ 
			tmp = *it; 
			if(tmp->OriFloor>m_iLocation) 
			{ 
				//消息队列中还有乘客所在楼层比当前楼层高 
				//电梯继续向上运行. 
				SetDirection(UP); 
				return; 
			} 
		} 
		for(pit = m_pltPassenger->begin();pit!=m_pltPassenger->end();pit++) 
		{ 
			ptmp = *pit; 
			if(ptmp->GetObjFloor()>m_iLocation) 
			{ 
				//电梯之中还有乘客要在当前楼层之上下梯. 
				SetDirection(UP); 
				return; 
			} 
		} 
		SetDirection(DOWN);  
		return;	 
	case DOWN: 
		for(it = m_ltMessages.begin(); it!= m_ltMessages.end(); it++) 
		{ 
			tmp = *it; 
			if(tmp->OriFloor < m_iLocation) 
			{ 
				//消息队列中还有乘客要上梯 
				//电梯继续向下 
				SetDirection(DOWN); 
				return; 
			} 
		} 
		for(pit = m_pltPassenger->begin();pit!=m_pltPassenger->end();pit++) 
		{ 
			ptmp = *pit; 
			if(ptmp->GetObjFloor() < m_iLocation) 
			{ 
				//电梯之中中还有乘客要下梯. 
				SetDirection(DOWN); 
				return; 
			} 
		} 
		SetDirection(UP);  
		return; 
	case NONE: 
		//如果电梯当前处于空闲状态,方向为NONE. 
		//取出消息队列中的第一个消息,由它决定电梯的运行方向. 
		tmp = m_ltMessages.front(); 
		if(tmp->OriFloor > m_iLocation ) SetDirection(UP); 
		if(tmp->OriFloor < m_iLocation) SetDirection(DOWN); 
		if(tmp->OriFloor==m_iLocation) 
		{ 
			//如果电梯正在该层,检查改乘客是否已经在电梯中 
			//分情况处理. 
			floor = GetFloor(m_iLocation); 
			pLst = floor->m_pltFPassengers; 
			ptmp = pLst->GetPassengerByPID(tmp->PID); 
			if(ptmp==NULL) 
			{ 
				if(tmp->ObjFloor > m_iLocation ) SetDirection(UP); 
				if(tmp->ObjFloor < m_iLocation)	 SetDirection(DOWN); 
			} 
			else SetStatus(WAIT); 
		} 
		return; 
	default: 
		break; 
	} 
} 
 
void CElevator::SetDirection(EDIRECTION dir) 
{ 
	m_enDirection = dir; 
} 
 
bool CElevator::IsQualifiedForRespondingCall(CMessage *msg) 
{ 
// 该函数回答监视对象的询问: 能否对该请求提供服务;	 
	if(!Reachable(msg->OriFloor) || !Reachable(msg->ObjFloor)) 
		return false; 
	//if(IsOverloading()&&abs(m_iLocation-msg->OriFloor)<3) return false; 
	if(IsIdle()) return true; 
	if(m_enDirection==UP) 
	{ 
		//同方向,当前楼层比请求者所在的楼层低 
		if(msg->Direction==RUP && m_iLocation <= msg->OriFloor) 
			return true; 
		//不同方向,最高的目标楼层比请求者所在的楼层低 
		//前提是当前层必须高于大于35层 
		if(msg->Direction==RDOWN && GetHighestToGo()OriFloor) 
			return true; 
	} 
	if(m_enDirection==DOWN) 
	{ 
		//同方向, 当前楼层比请求者所在的楼层高 
		if(msg->Direction==RDOWN && m_iLocation >= msg->OriFloor)  
			return true; 
		//不同方向,最低层比请求者所在的楼层高 
		//前提是已经有的请求小于5层 
		if(msg->Direction==RUP && GetLowestToGo() > msg->OriFloor) 
			return true; 
	} 
	return false; 
} 
 
bool CElevator::IsIdle() 
{ 
	if(m_enStatus==IDLE) return true; 
	else return false; 
} 
int CElevator::GetHighestToGo() 
{ 
//获得电梯此时要到的最高层 
	CMsgList::iterator it; 
	CMessage* tmp; 
	for(it=m_ltMessages.begin(); it!=m_ltMessages.end(); it++) 
	{ 
		tmp = *it; 
		if(tmp->OriFloor > 35 && tmp->OriFloor<=m_iLocation) 
			return tmp->OriFloor; 
		if(tmp->ObjFloor > 35 && tmp->OriFloor<=m_iLocation) 
			return tmp->ObjFloor; 
	} 
	return m_iLocation; 
} 
 
int CElevator::GetLowestToGo() 
{ 
// 获得电梯此时要到的最低层. 
	CMsgList::iterator it; 
	CMessage* tmp; 
	for(it = m_ltMessages.begin();it!=m_ltMessages.end();it++) 
	{ 
		tmp = *it; 
		if(tmp->OriFloor < 5 ) 
			return tmp->OriFloor; 
		if(tmp->ObjFloor < 5 ) 
			return tmp->ObjFloor; 
	} 
	return m_iLocation; 
} 
int CElevator::GetStopNums(CMessage *msg) 
{ 
// 获得电梯若要到达消息指定的源楼层需要停留的时间 
// 包括上下乘客的时间. 
	CPassengerList::iterator it1; 
	CMsgList::iterator it2; 
	CPassenger* tmp1; 
	CMessage* tmp2; 
	int iCount=0; 
//在乘客链表中找到在请求要上之前要下的乘客 
	for(it1 = m_pltPassenger->begin();it1 != m_pltPassenger->end();it1++) 
	{ 
		tmp1 = *it1; 
		if(m_enDirection==UP)  
		{ 
			if(tmp1->GetObjFloor()>=m_iLocation && tmp1->GetObjFloor()<=msg->OriFloor) 
			{ 
				iCount++; 
			} 
		} 
		if(m_enDirection==DOWN)  
		{ 
			if(tmp1->GetObjFloor()<=m_iLocation && tmp1->GetObjFloor()>=msg->OriFloor) 
			{ 
				iCount++; 
			} 
		} 
	} 
//在消息队列中找到在请求之前要下的乘客的个数 
	for(it2 = m_ltMessages.begin();it2 != m_ltMessages.end();it2++) 
	{ 
		tmp2 = *it2; 
		if(m_enDirection==UP)  
		{ 
			if(tmp2->OriFloor>=m_iLocation && tmp2->OriFloor <= msg->OriFloor) 
			{ 
				//该乘客在请求之前即下又上 
				if(tmp2->ObjFloor<=msg->OriFloor) iCount= iCount+2; 
				//上面已经计算过了 
				else iCount++; 
			} 
		} 
		if(m_enDirection==DOWN)  
		{ 
			if(tmp2->OriFloor <= m_iLocation && tmp2->OriFloor >= msg->OriFloor) 
			{ 
				if(tmp2->ObjFloor>=msg->OriFloor) iCount = iCount+2; 
				else iCount++; 
			} 
		} 
	} 
	return iCount; 
}