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; }