📄 maincontrol.cpp
字号:
// MainControl.cpp : 实现文件
//
#include "stdafx.h"
#include "MyVariousState.h"
#include "MainControl.h"
#include "MyWaitQueue.h"
#include "ElevatorThread.h"
// CMainControl 对话框
//IMPLEMENT_DYNAMIC(CMainControl, CDialog)
CMainControl::CMainControl(CWnd* pParent /*=NULL*/)
: CDialog(CMainControl::IDD, pParent)
{
str_arrElevatorName[0]='1';
str_arrElevatorName[1]='2';
str_arrElevatorName[2]='3';
str_arrElevatorName[3]='4';
str_arrElevatorName[4]='5';
iTotalFailTimes = 0;
}
CMainControl::~CMainControl()
{
}
void CMainControl::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CMainControl, CDialog)
ON_BN_CLICKED(IDCCANCEL, &CMainControl::OnBnClickedCcancel)
ON_BN_CLICKED(IDOK, &CMainControl::OnBnClickedOk)
ON_WM_DESTROY()
ON_WM_TIMER()
ON_COMMAND_RANGE(IDC_FLOORBUTTONS,IDC_FLOORBUTTONS+40,OnFloorBtnClk)
ON_MESSAGE(WM_ARRIVE_ONEFLOOR,OnOneFloorArrived)
END_MESSAGE_MAP()
// CMainControl 消息处理程序
BOOL CMainControl::OnInitDialog()
{
CDialog::OnInitDialog();
// TODO: Add extra initialization here
m_myQuit.SubclassDlgItem(IDOK,this);
m_myAbout.SubclassDlgItem(IDCCANCEL,this);
//===========创建动态楼层按钮
CString strCaption;
int iFloorbtnLeft = 25;
int iFloorbtnTop = 350;
int iColWidth = 80;
int iRowHeight = 65;
int iFloorbtnWidth = 55;
int iFloorbtnHeight = 25;
int i;
try{
for(i=MAX_FLOOR_NUM;i>0;i--)
{
strCaption.Format(_T("%d"),i);
m_pFloorButton[i-1][0]=new MyButton;
m_pFloorButton[i-1][1]=new MyButton;
m_pFloorButton[i-1][0]->Create(strCaption+"↑",BS_PUSHBUTTON|WS_CHILD|WS_VISIBLE,\
CRect(iFloorbtnLeft,iFloorbtnTop+(10-i)*iRowHeight/2,iFloorbtnLeft+iFloorbtnWidth,iFloorbtnTop+(10-i)*iRowHeight/2+iFloorbtnHeight),\
this,IDC_FLOORBUTTONS+2*(i-1));
m_pFloorButton[i-1][1]->Create(strCaption+"↓",BS_PUSHBUTTON|WS_CHILD|WS_VISIBLE,\
CRect(iFloorbtnLeft+iColWidth,iFloorbtnTop+(10-i)*iRowHeight/2,iFloorbtnLeft+iColWidth+iFloorbtnWidth,iFloorbtnTop+(10-i)*iRowHeight/2+iFloorbtnHeight),\
this,IDC_FLOORBUTTONS+2*(i-1)+1);
}
}
catch(CException* e)
{
AfxMessageBox(_T("无法创建楼层按钮,程序不能正常运行。"));
e->ReportError();
e->Delete();
return FALSE;//退出!
}
//隐藏掉两个无用的按钮
m_pFloorButton[19][0]->ShowWindow(FALSE);
m_pFloorButton[0][1]->ShowWindow(FALSE);
////////////////////////////////创建电梯///////////////////////
try{
for(i=0;i<MAX_ELEVATOR_NUM;i++)
{
m_elevatorArr[i] = new CMyElevatorThread(i+1,this);
m_elevatorArr[i]->Create(IDD_MYELEVATOR_DIALOG,this);
m_elevatorArr[i]->MoveWindow(CRect(i*205+210,15,(i+1)*205+210,755));
m_elevatorArr[i]->ShowWindow(SW_SHOW);
}
}
catch(CException* e)
{
AfxMessageBox(_T("无法创建电梯,程序不能正常运行。"));
e->ReportError();
e->Delete();
return FALSE;//退出!
}
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void CMainControl::OnBnClickedCcancel()
{
// TODO: 在此添加控件通知处理程序代码
//if(IDYES==MessageBox(_T("是否真的结束程序?"),_T("电梯系统"),MB_YESNO))
//CDialog::OnOK();
CAboutDlg dlg;
dlg.DoModal();
}
void CMainControl::OnBnClickedOk()
{
// TODO: 在此添加控件通知处理程序代码
if(IDYES==MessageBox(_T("是否真的结束程序?"),_T("电梯调度系统"),MB_YESNO))
OnOK();
}
void CMainControl::OnDestroy()
{
CDialog::OnDestroy();
// TODO: Add your message handler code here
int i;
for(i=0;i<MAX_ELEVATOR_NUM;i++)
{
delete m_elevatorArr[i];
}
for(i=0;i<MAX_FLOOR_NUM;i++)
{
delete m_pFloorButton[i][0];
delete m_pFloorButton[i][1];
}
KillTimer(1);
lWaitQueue.~CMyWaitQueue();
}
//主控中心响应外部按钮
void CMainControl::OnFloorBtnClk(UINT curBtn)
{
// TODO: Add your control notification handler code here
int iReqFloor =curBtn-1100+1;
sOuterRequest tmpOuterRequest = ChangeReqStruct(iReqFloor);
if((lWaitQueue.searchNode(tmpOuterRequest)) > 0)
{
AfxMessageBox(_T("请不要重复请求。"));
return;
}
GetDlgItem(curBtn)->EnableWindow(FALSE);
trytoSchedule(tmpOuterRequest);//立即尝试分派!
}
//主控中心将外部按钮转换成内部消息传递
sOuterRequest CMainControl::ChangeReqStruct(int iNo)
{
sOuterRequest tempVal;
if(iNo%2==0)
{
tempVal.eMyReqDirection =DOWN;
}
else
{
tempVal.eMyReqDirection =UP;
iNo++;
}
tempVal.iMyReqFloor = iNo/2;
tempVal.iMyReqTime =0;
tempVal.bMyReClaimed = FALSE;
return tempVal;
}
int CMainControl::ChangeReqStruct2(const sOuterRequest& tmpRequest)
{
return (tmpRequest.eMyReqDirection==UP) ? (2*(tmpRequest.iMyReqFloor-1)) : (2*(tmpRequest.iMyReqFloor-1)+1);
}
int CMainControl::GoodnessEle(const sOuterRequest& tmpOuterRequest)
{
int returnVal = -1;
//挨个查看各正常电梯的状态
int tmpCurFloor;
int tmpCurWeight;
int tmpPrioValue;
bool tmpCanSchedule;
enum state tmpState;
int iPrioValue = 10000;//优先数,优先数越小优先级越大
for(int i=0;i<MAX_ELEVATOR_NUM; i++)
{
tmpState = m_elevatorArr[i]->getState();
tmpCurFloor = m_elevatorArr[i]->getCurFloor();
tmpCurWeight=m_elevatorArr[i]->getCurPassengerNum();
tmpCanSchedule = m_elevatorArr[i]->canSchedule();
if(tmpState!=MAL_FUNCTION && tmpCanSchedule)
{
if(tmpState==Ele_IDLE||(tmpOuterRequest.eMyReqDirection==UP && (tmpState==Ele_UP_RUN || tmpState==Ele_UP_PAUSE)) || \
(tmpOuterRequest.eMyReqDirection==DOWN && (tmpState==Ele_DOWN_RUN || tmpState==Ele_DOWN_PAUSE)) )
{
if(tmpState==Ele_IDLE)
{
//计算该电梯的优先数
tmpPrioValue = DIST_PRIO*abs(tmpOuterRequest.iMyReqFloor-tmpCurFloor)+WEIGHT_PRIO*tmpCurWeight;
if(tmpPrioValue<iPrioValue)
{
iPrioValue = tmpPrioValue;
returnVal = i;
}
}
if(tmpOuterRequest.eMyReqDirection==UP && tmpOuterRequest.iMyReqFloor>=tmpCurFloor)
{
//计算该电梯的优先数
tmpPrioValue = DIST_PRIO*(tmpOuterRequest.iMyReqFloor-tmpCurFloor)+\
WEIGHT_PRIO*tmpCurWeight;
if(tmpPrioValue<iPrioValue)
{
iPrioValue = tmpPrioValue;
returnVal = i;
}
}
if(tmpOuterRequest.eMyReqDirection==DOWN && tmpOuterRequest.iMyReqFloor<=tmpCurFloor)
{
//计算该电梯的优先数
tmpPrioValue = DIST_PRIO*(tmpCurFloor-tmpOuterRequest.iMyReqFloor)+\
WEIGHT_PRIO*tmpCurWeight;
if(tmpPrioValue<iPrioValue)
{
iPrioValue = tmpPrioValue;
returnVal = i;
}
}
}
}
}
return returnVal;
}
void CMainControl::Schedule()
{
if(lWaitQueue.getLength() == 0)
{
KillTimer(1);//队列空了,歇会
return;
}
int iReqFloor;
CString tempString,tempString1;
sOuterRequest tmpOuterRequest;
while(lWaitQueue.cutHead(tmpOuterRequest) && !tmpOuterRequest.bMyReClaimed)
{
if(tmpOuterRequest.iMyReqTime < BAD_REQUEST_TIME)//如果此请求长时间没有得到分配,则直接删除
{
trytoSchedule(tmpOuterRequest);
}
else//对于长时间不能调度出去的请求也要处理一下
{
iReqFloor = ChangeReqStruct2(tmpOuterRequest);//转换成请求按钮号
GetDlgItem(IDC_FLOORBUTTONS+iReqFloor)->EnableWindow(TRUE);
iTotalFailTimes++;//递增总调度失败次数
tempString.Format(_T("%d"),tmpOuterRequest.iMyReqFloor);
tempString1 = (tmpOuterRequest.eMyReqDirection==UP) ? "↑":"↓";
AfxMessageBox(_T("很抱歉,下面的请求因超时而被系统取消,请重新请求。\r\n")+tempString+tempString1);
}
}
//将本次追加到队尾的请求标识位恢复
if(tmpOuterRequest.bMyReClaimed){
tmpOuterRequest.bMyReClaimed = FALSE;
lWaitQueue.appendTail(tmpOuterRequest);
}
lWaitQueue.refreshLink();
}
void CMainControl::trytoSchedule(sOuterRequest& tmpRequest)
{
int targetElevator=-1,iReqFloor;
CString tempString,tempString1;
if((targetElevator = GoodnessEle(tmpRequest))<0)//目前没有找到合适的接受者,再放入
{
tmpRequest.iMyReqTime++;
tmpRequest.bMyReClaimed = TRUE;
lWaitQueue.appendTail(tmpRequest);
}
else //发消息给目标电梯
{
//对于电梯刚好在当前楼层的情况,电梯的返回往往比下面的程序段还要快!
//所以此段程序不能跟下面的那行调换位置!!!
tempString1.Format(_T("%c"),str_arrElevatorName[targetElevator]);
iReqFloor = ChangeReqStruct2(tmpRequest);//转换成请求按钮号
GetDlgItem(IDC_FLOORBUTTONS+iReqFloor)->GetWindowText(tempString);
GetDlgItem(IDC_FLOORBUTTONS+iReqFloor)->SetWindowText(tempString+"("+tempString1+")");
m_elevatorArr[targetElevator]->acceptReq(tmpRequest);
}
KillTimer(1);
SetTimer(1,WAIT_INTERVAL*1000,NULL);//启动主控中心调度定时器
}
void CMainControl::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
switch(nIDEvent)
{
case 1:
Schedule();
break;
}
CDialog::OnTimer(nIDEvent);
}
LONG CMainControl::OnOneFloorArrived(WPARAM wP,LPARAM lP)
{
int iReqFloor=(int)wP;
CString tempString;
GetDlgItem(IDC_FLOORBUTTONS+iReqFloor)->EnableWindow(TRUE);
//m_elevatorArr[1]->m_ElevatorBox.SetBkColor(RGB(0,0,0));
GetDlgItem(IDC_FLOORBUTTONS+iReqFloor)->GetWindowText(tempString);
if(tempString.GetLength() >4 )
{
tempString = tempString.Mid(0,tempString.GetLength()-3);
GetDlgItem(IDC_FLOORBUTTONS+iReqFloor)->SetWindowText(tempString);
}
//Invalidate(); //重画窗体
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -