电梯调度小程序。
小组成员:付亚飞 段兴林
对于第一种状态即电梯正在向下运动,大概思路如下:除底层和顶层只有一个按钮外,每个楼层有两个按钮,分别指示上楼和下楼请求,当按下后,按钮灯亮,实时监控程序负责判断乘客的上下楼请求是否与电梯的当前运动方向一致,若不一致,则暂不受理此请求;若一致,让电梯平稳地停在此层楼的电梯入口处,让相应的乘客入电梯,而后继续朝原方向运动。若同时有两层或两层以上的楼发出请求,产生了冲突,则监控器调用冲突处理器进行抉择,受理其中的一个请求。这种情况还可以细分为有人与没人两种情况。
当第一种状态的电梯里有人时,那么电梯向着最近的目标楼层驶去,如果此时中途有人有向下的请求且电梯可以到达,那么改变电梯的目标楼层,使电梯在有人处停止。
当第一种状态的电梯里(即正处于向下运动)没人时,假设此时的电梯所在的层数为i,那么搜索 i-1到0层间是否有向下的请求,如果有那么将最近的一个请求所在楼层设为目标,如果没有,那么在搜索0到i-1层间是否向上的请求,如果有将最远的一个请求所在的楼层设为目标。
第二种情况与第一种类似,再此不做多述。
对于第三种情况的电梯即处于开门状态或者处于关门但是没有明确目标的电梯。同样分为有人与没人两种状态,若有人,那么找到这些人想去的最近的目标楼层,若没人将目标楼层设为整个楼层中请求最早的地方。
我们的算法功能不是很强大,当处理多台电梯怎么分配任务时我们是这么处理的,比如,1,3号电梯都正向上走它们处于7层以下,若此时7,9层有向上的请求,那么我们将第7层的请求分给离7层最近的电梯,比如为1,那么就会将9层的响应分给3。在分配时我们采取最近的判断标准,谁离得近就将任务分配给谁。
还有一个最重要的地方,就是超重的问题,比如如果电梯载重达到极限,那么电梯就不再响应乘客的请求了,除非有人走下电梯。
经过一个星期的奋斗,我们终于把界面大致做出来了,虽然不太好看,但基本满足课题的要求,截图如下:
public class TubePanel extends JPanel{ private int curFloor= 1; private short curStatus = 0; //0 ---表示电梯静止。 1----表示电梯运动, 2--表示电梯里面没有人了 private final static int elevatorWidth = 48; private final static int elevatorHeight = 19; public void setCurFloor( int cf){ if( cf <1 || cf > 20){ return ; } curFloor = cf; this.repaint(); } public void closeDoor(){ curStatus = 1; this.repaint(); System.out.println(" door close"); } public void openDoor (){ curStatus = 0; this.repaint(); System.out.println( " door Open"); } public void allUnload(){ curStatus = 2; this.repaint(); System.out.println( " all unload"); } public TubePanel(){ this.setSize(52, 402); this.setBackground( new Color(0,255,0)); } public void paintComponent(Graphics g){ super.paintComponents(g); Graphics2D g2 = (Graphics2D)g; int curFloorY = (20-curFloor)*20; //画通道 Rectangle2D tube = new Rectangle2D.Double(0, 0,50, 400); g2.draw(tube); g2.fill(tube); //画绳索 g2.setColor( new Color(255,0,0) ); Rectangle2D rope = new Rectangle2D.Double( elevatorWidth/2,0 ,2, curFloorY ) ; g2.draw(rope); Rectangle2D elevator = new Rectangle2D.Double(1, curFloorY-1, elevatorWidth, elevatorHeight); if( curStatus == 1 ){ //电梯运行 g2.setColor( new Color(255,0,0)); g2.fill(elevator); g2.setColor( new Color(0,255,0)); g2.draw(elevator); g2.setColor( new Color(0,0,0)); g2.setFont(new Font("Times New Roman", Font.BOLD, 15)); g2.drawString(""+curFloor, elevatorWidth/2-7, curFloorY+elevatorHeight*2/3); }else if ( curStatus == 0 ){//0 ---表示电梯静止 g2.setColor( new Color(0,255,0)); g2.fill(elevator); g2.setColor( new Color(255,0,0)); g2.draw(elevator); g2.setColor( new Color(0,0,0)); g2.setFont(new Font("Times New Roman", Font.PLAIN, 15)); g2.drawString("waiting...", 5, curFloorY+elevatorHeight*2/3); }else {// 2--表示电梯里面没有人了 g2.setColor( new Color(0,0,255)); g2.fill(elevator); g2.setColor( new Color(255,0,0)); g2.draw(elevator); g2.setColor( new Color(0,0,0)); g2.setFont(new Font("Times New Roman", Font.PLAIN, 15)); g2.drawString("all free", 5, curFloorY+elevatorHeight*2/3); } } }
程序设计流程:
电梯状态 |
电梯命令 |
乘客请求事件 |
最高层数 |
添加电梯停时响应事件 |
X楼上行请求 |
剩余负载 |
取消电梯停时响应事件 |
X楼下行请求 |
运行方向(上、下、静止) |
E电梯内有乘客请求去Y楼 |
|
能否到达X楼 |
开往X楼 |
|
开往(静止时:上、下) |
设置开往方向(上、下) |
在功能实现上,主要是靠下面的代码实现的:
public class ElevatorThread extends Thread{ int curPos = 1; boolean direction = true; //方向, 上--true; 下----false boolean status = false; //电梯的状态, true -----正在运行, false----等待prey. private TubePanel tubePanel; int threadID; TreeSet destSet = new TreeSet(); public ElevatorThread( TubePanel p){ tubePanel = p; start(); } public void setThreadID( int i ){ threadID = i; } public synchronized void addDest( int dest ){ destSet.add(new Integer(dest)); } public synchronized void addDestNotify( int dest ){ destSet.add(new Integer( dest )); this.notify(); } public void run(){ while( true){ status = false; try{ synchronized ( this ){ wait(); } status = true; System.out.println("Thread " + threadID + " begin to run"); while( !destSet.isEmpty() ){ Integer integer = (Integer)destSet.first(); int dest = (integer).intValue(); System.out.println("dest is " + dest); tubePanel.closeDoor(); //电梯关门 , 开始向一个目的楼层行进 while( curPos != dest ){ if( curPos < dest ){ curPos ++; direction = true; tubePanel.setCurFloor(curPos); }else { curPos --; direction = false; tubePanel.setCurFloor(curPos); } System.out.println("Thread " + threadID + " now at " + curPos ); sleep(500); integer = (Integer)destSet.first(); dest = (integer).intValue(); } //电梯开门, 一个目标楼层已到达 System.out.println("Thread " + threadID + " arrive at " + curPos + " Floor" ); destSet.remove(integer); tubePanel.openDoor(); sleep(2000); } tubePanel.allUnload(); //如果所有的目的楼层都经过了, 则电梯的状态为全部卸载 status = false; }catch( InterruptedException e){ e.printStackTrace(); } } } }