电梯调度程序开发 付亚飞 段兴林

    小组成员:付亚飞  段兴林
这次的结对项目是关于电梯调度算法的实现,要实现电梯调度的最佳算法,平均总旅行时间越低越好。
 
    电梯一般分为三种情况,电梯正在向下运动,正在向上运动或者处于停止中。由于第一种状态与第二种状态类似,我们组只讨论了第一种和第三种状态。

       对于第一种状态即电梯正在向下运动,大概思路如下:除底层和顶层只有一个按钮外,每个楼层有两个按钮,分别指示上楼和下楼请求,当按下后,按钮灯亮,实时监控程序负责判断乘客的上下楼请求是否与电梯的当前运动方向一致,若不一致,则暂不受理此请求;若一致,让电梯平稳地停在此层楼的电梯入口处,让相应的乘客入电梯,而后继续朝原方向运动。若同时有两层或两层以上的楼发出请求,产生了冲突,则监控器调用冲突处理器进行抉择,受理其中的一个请求。这种情况还可以细分为有人与没人两种情况。

         当第一种状态的电梯里有人时,那么电梯向着最近的目标楼层驶去,如果此时中途有人有向下的请求且电梯可以到达,那么改变电梯的目标楼层,使电梯在有人处停止。

        当第一种状态的电梯里(即正处于向下运动)没人时,假设此时的电梯所在的层数为i,那么搜索 i-1到0层间是否有向下的请求,如果有那么将最近的一个请求所在楼层设为目标,如果没有,那么在搜索0到i-1层间是否向上的请求,如果有将最远的一个请求所在的楼层设为目标。

     第二种情况与第一种类似,再此不做多述。

   对于第三种情况的电梯即处于开门状态或者处于关门但是没有明确目标的电梯。同样分为有人与没人两种状态,若有人,那么找到这些人想去的最近的目标楼层,若没人将目标楼层设为整个楼层中请求最早的地方。

       我们的算法功能不是很强大,当处理多台电梯怎么分配任务时我们是这么处理的,比如,1,3号电梯都正向上走它们处于7层以下,若此时7,9层有向上的请求,那么我们将第7层的请求分给离7层最近的电梯,比如为1,那么就会将9层的响应分给3。在分配时我们采取最近的判断标准,谁离得近就将任务分配给谁。

还有一个最重要的地方,就是超重的问题,比如如果电梯载重达到极限,那么电梯就不再响应乘客的请求了,除非有人走下电梯。

    经过一个星期的奋斗,我们终于把界面大致做出来了,虽然不太好看,但基本满足课题的要求,截图如下:

 

我们是使用java编写的界面,当然我们参考了相关课本和网上的教程,程序功能上还不太健全,主要代码如下:

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

 这是我们组完成项目的时间安排:

 
原文地址:https://www.cnblogs.com/feiji/p/3589581.html