电梯运行学习心得

引言

这是一篇我完成一次大作业的迭代的学习心得,这次作业有收获和不足,对于刚学习面向对象的我来说这次作业难度还是很大的,所以进行了这次作业复盘,希望能提醒自己。

实验目标

这次电梯运行是为了培养我的面向对象的思维,改掉原来学习C语言的面向程序的旧思想,培养封装成类的思维,为后续代码打基础,更好的为以后学习面向对象程序语言。

第一次实验迭代

题目

设计一个电梯类,具体包含电梯的最大楼层数、最小楼层数(默认为1层)当前楼层、运行方向、运行状态,以及电梯内部乘客的请求队列和电梯外部楼层乘客的请求队列,其中,电梯外部请求队列需要区分上行和下行。
电梯运行规则如下:电梯默认停留在1层,状态为静止,当有乘客对电梯发起请求时(各楼层电梯外部乘客按下上行或者下行按钮或者电梯内部乘客按下想要到达的楼层数字按钮),电梯开始移动,当电梯向某个方向移动时,优先处理同方向的请求,当同方向的请求均被处理完毕然后再处理相反方向的请求。电梯运行过程中的状态包括停止、移动中、开门、关门等状态。当电梯停止时,如果有新的请求,就根据请求的方向或位置决定移动方向。电梯在运行到某一楼层时,检查当前是否有请求(访问电梯内请求队列和电梯外请求队列),然后据此决定移动方向。每次移动一个楼层,检查是否有需要停靠的请求,如果有,则开门,处理该楼层的请求,然后关门继续移动。
使用键盘模拟输入乘客的请求,此时要注意处理无效请求情况,例如无效楼层请求,比如超过大楼的最高或最低楼层。还需要考虑电梯的空闲状态,当没有请求时,电梯停留在当前楼层。
请编写一个Java程序,设计一个电梯类,包含状态管理、请求队列管理以及调度算法,并使用一些测试用例,模拟不同的请求顺序,观察电梯的行为是否符合预期,比如是否优先处理同方向的请求,是否在移动过程中处理顺路的请求等。为了降低编程难度,不考虑同时有多个乘客请求同时发生的情况,即采用串行处理乘客的请求方式(电梯只按照规则响应请求队列中当前的乘客请求,响应结束后再响应下一个请求),具体运行规则详见输入输出样例。

输入格式:
第一行输入最小电梯楼层数。
第二行输入最大电梯楼层数。
从第三行开始每行输入代表一个乘客请求。

电梯内乘客请求格式:<楼层数>
电梯外乘客请求格式:<乘客所在楼层数,乘梯方向>,其中,乘梯方向用UP代表上行,用DOWN代表下行(UP、DOWN必须大写)。
当输入“end”时代表输入结束(end不区分大小写)。
输出格式:
模拟电梯的运行过程,输出方式如下:

运行到某一楼层(不需要停留开门),输出一行文本:
Current Floor: 楼层数 Direction: 方向
运行到某一楼层(需要停留开门)输出两行文本:
Open Door # Floor 楼层数
Close Door


SourceMonitor分析

image

类图

image

  1. 功能介绍
  • 核心功能:实现电梯完成处理每个队列的第一个请求的功能,使电梯能打印电梯运行信息
  1. 主要方法和类
  • 1、方法:
    void removeAsk():移除到达楼层的请求
    void checkAsk(String ask):检查请求是否合法并添加到相应列表
    void confirmDirection():确定电梯运行方向
  • 2、类:
    Main:主函数
    Elevator:电梯的内部运行规则及其电梯属性
  1. 代码结构
    因为只有一个类所以所有的代码全部杂糅在Eveator里结构比较混乱,方法里要互相使用电梯属性
  2. 存在的为题与不足
    某些方法的使用逻辑有问题,没有完成老师补充样例中的一个,主要是在确定方向和确定电梯是否停下来并开门这里有问题,确定电梯运行需要先停下来把表头的请求再确定电梯运行的方向,而确定电梯是否停下来要先确定方向所以两个方法互相作用就不能正确的完成电梯逻辑,但是时间到了截至的时间而且下一次的迭代题目也来了就没有在进行深入,问题依然存在。

第二次迭代代码分析

题目

对之前电梯调度程序进行迭代性设计,目的为解决电梯类职责过多的问题,类设计要求遵循单一职责原则(SRP),要求必须包含但不限于设计电梯类、乘客请求类、队列类以及控制类。
电梯运行规则与前阶段单类设计相同,但要处理如下情况:

乘客请求楼层数有误,具体为高于最高楼层数或低于最低楼层数,处理方法:程序自动忽略此类输入,继续执行
乘客请求不合理,具体为输入时出现连续的相同请求,例如<3><3><3>或者<5,DOWN><5,DOWN>,处理方法:程序自动忽略相同的多余输入,继续执行,例如<3><3><3>过滤为<3>
注意:本次作业类设计必须符合如上要求(包含但不限于乘客请求类、电梯类、请求队列类及控制类,其中控制类专门负责电梯调度过程),凡是不符合类设计要求此题不得分,另外,PTA得分代码界定为第一次提交的最高分代码(因此千万不要把第一次电梯程序提交到本次题目中测试)。

输入格式:
第一行输入最小电梯楼层数。
第二行输入最大电梯楼层数。
从第三行开始每行输入代表一个乘客请求。

电梯内乘客请求格式:<楼层数>
电梯外乘客请求格式:<乘客所在楼层数,乘梯方向>,其中,乘梯方向用UP代表上行,用DOWN代表下行(UP、DOWN必须大写)。
当输入“end”时代表输入结束(end不区分大小写)。
输出格式:
模拟电梯的运行过程,输出方式如下:

运行到某一楼层(不需要停留开门),输出一行文本:
Current Floor: 楼层数 Direction: 方向
运行到某一楼层(需要停留开门)输出两行文本:
Open Door # Floor 楼层数
Close Door


SourceMonit分析

image

类图

image

  1. 改进之处:将Elevator类分成了Control、RequestQueue和ExternalRequest三个类,一定程度上减轻了单一类的职责。
  2. 优化
    将外部请求的方法设置为类,使得其中的方向和楼层变成属性使用更加方便
  3. 不足
    第二次迭代并没有解决第一次遗留的关门和确定电梯方向的矛盾问题。代码中还有一些重复的功能,还有是写代码的时候没有时间写注释,所以比较难懂,修改起来需要我一个一个去找。

第三次迭代代码分析

题目

对之前电梯调度程序再次进行迭代性设计,加入乘客类(Passenger),取消乘客请求类,类设计要求遵循单一职责原则(SRP),要求必须包含但不限于设计电梯类、乘客类、队列类以及控制类,具体设计
电梯运行规则与前阶段相同,但有如下变动情况:

乘客请求输入变动情况:外部请求由之前的<请求楼层数,请求方向>修改为<请求源楼层,请求目的楼层>
对于外部请求,当电梯处理该请求之后(该请求出队),要将<请求源楼层,请求目的楼层>中的请求目的楼层加入到请求内部队列(加到队尾)
注意:本次作业类设计必须符合如上要求(包含但不限于设计电梯类、乘客类、队列类以及控制类),凡是不符合类设计要求此题不得分,另外,PTA得分代码界定为第一次提交的最高分代码(因此千万不要把第一次及第二次电梯程序提交到本次题目中测试)。

输入格式:
第一行输入最小电梯楼层数。
第二行输入最大电梯楼层数。
从第三行开始每行输入代表一个乘客请求。

电梯内乘客请求格式:<楼层数>
电梯外乘客请求格式:<请求源楼层,请求目的楼层>,其中,请求源楼层表示乘客发起请求所在的楼层,请求目的楼层表示乘客想要到达的楼层。
当输入“end”时代表输入结束(end不区分大小写)。
输出格式:
模拟电梯的运行过程,输出方式如下:

运行到某一楼层(不需要停留开门),输出一行文本:
Current Floor: 楼层数 Direction: 方向
运行到某一楼层(需要停留开门)输出两行文本:
Open Door # Floor 楼层数
Close Door


SourceMonitor分析

image

类图

image

  1. 完善内容
    进一步细分类,使其符合单一职责原则,电梯类只是提供电梯,请求类,乘客类的基础属性,将电梯控制的方法全部放在控制类,使得代码条理更加清晰。
  2. 优化结果
    考虑到题目的更新,原来两次的代码逻辑存在错误,因为题目要求把外部请求的目标楼层加入到内部请求队尾,使得原来能通过的错误代码逻辑无法通过这次,所以我思考了如何解决关门和确定电梯运行方向矛盾,既然电梯关门和确定电梯方向有关所以我把确定电梯方向放在了关门之前,但是这时候电梯方向不能是原来的电梯方向,所以我再次将确定电梯方向的方法放到了关门的后面,即用两次确定电梯方向的方法,再次运行代码成功通过测试。
  3. 不足
    代码注释仍旧缺失,所以维修成本仍旧过高,每次修改代码都要先看一下代码逻辑,有点不方便,因为代码逻辑和原来类似,所以重复的方法调用问题仍旧存在。

迭代效果对比与总结

  1. 代码内容对比
    相同点:三次代码逻辑基本相同,方法内容也基本相同、
    不同点:前两次存在代码逻辑问题,第三次修复了代码逻辑,解决了代码有时候出问题的问题。
  2. 代码质量对比
    第一代码只用了两个类,之后类的数量逐渐升高,代码的复用性也逐渐升高,代码质量逐渐升高。
  3. 迭代过程中的经验和教训
    在迭代过程中,因为代码的注释比较少,所以有时侯修改起来比较难,但是代码逻辑基本一致所以在修改时主要对着改,修改部分代码即可。代码分支比较多,有的时候很难做到不眼花,想着想着头就开始痛了。

学习心得

经过这次实验,我体会到面向对象代码的实用性,对比面向程序的代码,我只需要修改一个类的内容就可以修改其他部分的内容,但是面向对象的程序代码量比较大,写起来比较费力费时,而且因为要对类进行封装,需要很多重复的setter和getter的方法,有时候会写的比较难受,而且面向对象对提前预处理要求比较高,写之前需要先构思一下很容易一步错步步错,重新把代码删掉在重新写的时候真的令人崩溃。但总的来说,面向对象的优点还是比缺点多太多,只要思路是正确,明确每个类,每个方法的职责,后期修改起来真的很方便,或许这也是为什么面向对象语言能这么受欢迎吧。

代码详情

  1. 第一次迭代代码
点击查看代码
import java.util.*;

public class Main {
    public static void main (String[] args){
        Scanner scanner = new Scanner(System.in);
        Elevator a = new Elevator();
        a.minFloor = scanner.nextInt();
        a.maxFloor = scanner.nextInt();
        scanner.nextLine();
        while(true){
            String ask = scanner.nextLine();
            if(ask.equalsIgnoreCase("end")) break;
            else a.checkAsk(ask);
        }
        for(;!a.inner.isEmpty()||!a.outter.isEmpty();){
            a.printCurrentFloor();
            a.isStopped();
            a.confirmDirection();
            //a.isStopped();
            a.setCurrentFloor();
        }
        a.direction = "NO";
        scanner.close();
    }
}

class Elevator {
    int maxFloor;
    int minFloor;
    int currentFloor = 1;
    String status = "STOP";
    String direction = "UP";
    ArrayList<String> inner = new ArrayList<>();
    ArrayList<String> outter = new ArrayList<>();

    // 添加内部请求
    void createInnerAsk(String ask){
        inner.add(ask);
    }

    // 添加外部请求
    void createOutAsk(String ask){
        outter.add(ask);
    }

    // 移除到达楼层的请求
    void removeAsk(){
        if(!inner.isEmpty() && useAskInt(inner.get(0)) == currentFloor) inner.remove(0);
        if(!outter.isEmpty() && useAskInt(outter.get(0)) == currentFloor) outter.remove(0);
    }

    // 检查请求是否合法并添加到相应列表
    void checkAsk(String ask){
        if (!ask.matches("<\\d+(,\\w+)?>")) return;
        int floor = useAskInt(ask);
        if(floor <= maxFloor && floor >= minFloor){
            if(ask.contains(",")) createOutAsk(ask);
            else createInnerAsk(ask);
        }
    }

    // 从请求中提取楼层号
    int useAskInt(String ask){
        if(ask.contains(",")) return Integer.parseInt(ask.substring(ask.indexOf('<') + 1, ask.indexOf(',')));
        else return Integer.parseInt(ask.substring(ask.indexOf('<') + 1, ask.indexOf('>')));
    }

    // 从请求中提取请求方向
    String useAsk(String ask){
        return ask.substring(ask.indexOf(',') + 1, ask.lastIndexOf('>'));
    }

    // 判断是否需要在当前楼层停下开门
    void isStopped(){
        if (shouldStopAtInnerFloor()) {
            openDoor();
            removeAsk();
        }
        if (shouldStopAtOutterFloor()) {
            openDoor();
            removeAsk();
        }
    }

    // 判断是否需要在内部请求楼层停下
    private boolean shouldStopAtInnerFloor() {
        return !inner.isEmpty() && currentFloor == useAskInt(inner.get(0));
    }

    // 判断是否需要在外部请求楼层停下
    private boolean shouldStopAtOutterFloor() {
        if(!inner.isEmpty()) return !outter.isEmpty() && currentFloor == useAskInt(outter.get(0)) && direction.equals(useAsk(outter.get(0)));
        else return !outter.isEmpty() && currentFloor == useAskInt(outter.get(0));
    }

    // 输出开门和关门信息
    void openDoor(){
        System.out.println("Open Door # Floor " + currentFloor + "\n" + "Close Door");
    }

    // 更新当前楼层
    void setCurrentFloor() {
        if (direction.equals("UP") && currentFloor < maxFloor) currentFloor++;
        else if (direction.equals("DOWN") && currentFloor > minFloor) currentFloor--;
    }

    // 判断内部请求方向
    Boolean confirmInnerDirection(){
        if(!inner.isEmpty() && currentFloor == useAskInt(inner.get(0)))
            return direction.equals("UP");
        return useAskInt(inner.get(0)) > currentFloor;
    }

    // 判断外部请求方向
    Boolean confirmOutterDirection(){
        if(!outter.isEmpty() && currentFloor == useAskInt(outter.get(0)))
            return direction.equals("UP");
        return useAskInt(outter.get(0)) > currentFloor;
    }

    // 确定电梯运行方向
    void confirmDirection(){
        if(!inner.isEmpty() && !outter.isEmpty()) {
            if(direction.equals("UP")) {
                if(confirmInnerDirection() || confirmOutterDirection()) {direction = "UP";}
                else {direction = "DOWN";}
            } else if(direction.equals("DOWN")) {
                if(!confirmOutterDirection() || !confirmInnerDirection()) {direction = "DOWN";}
                else {direction = "UP";}
            } else {

                direction = "UP";
            }
        } else if(inner.isEmpty() && !outter.isEmpty()) {

            direction = confirmOutterDirection()? "UP" : "DOWN";
        } else if(outter.isEmpty() && !inner.isEmpty()) {

            direction = confirmInnerDirection()? "UP" : "DOWN";
        }
    }

    // 输出当前楼层和运行方向
    void printCurrentFloor(){
        System.out.println("Current Floor: " + currentFloor + " Direction: " + direction);
    }
}
  1. 第二次迭代代码
点击查看代码
import java.util.*;

public class Main {
    public static void main (String[] args){
        Scanner scanner = new Scanner(System.in);
        RequestQueue queue = new RequestQueue();
        LinkedList<Integer> internalRequest = new LinkedList<Integer>();
        int minFloor = scanner.nextInt();
        int maxFloor = scanner.nextInt();
        scanner.nextLine();
        while(true){
            String ask = scanner.nextLine();
            if(ask.equalsIgnoreCase("end")) break;
            queue.allRequest.add(ask);
        }
        scanner.close();
        Elevator elevator = new Elevator(minFloor,maxFloor);
        Controller a =new Controller(elevator,queue);
        a.processRequest();
        while(!a.getQueue().getInternalRequest().isEmpty()||!a.getQueue().getExternalRequest().isEmpty()){
            a.move();
            a.openDoor();
            a.determineDirection();
            a.getNextFloor();
        }
    }
}

enum Direction {
    UP,DOWN,IDLE;
}

enum State{
    MOVING,STOPPED;
}

class ExternalRequest{
    private Integer floor;
    private Direction direction;
    ExternalRequest(Integer floor,Direction direction){
        this.floor = floor;
        this.direction = direction;
    }
    public Integer getFloor(){
        return floor;
    }
    public Direction getDirection(){
        return direction;
    }
}

class RequestQueue{
    private LinkedList<Integer> internalRequest = new LinkedList<Integer>();
    private LinkedList<ExternalRequest> externalRequest = new LinkedList<ExternalRequest>();
    LinkedList<String> allRequest = new LinkedList<String>();
    public RequestQueue getQueueInstance(){
        return this;
    }
    public LinkedList<Integer> getInternalRequest(){
        return internalRequest;
    }
    public void setInternalRequest(LinkedList<Integer> internalRequest){
        this.internalRequest = internalRequest;
    }
    public LinkedList<ExternalRequest> getExternalRequest(){
        return externalRequest;
    }
    public void setExternalRequest(LinkedList<ExternalRequest> externalRequest){
        this.externalRequest = externalRequest;
    }
    public void addInternalRequest(int floor){
        internalRequest.add(floor);
    }
    public void addExternalRequest(int floor,Direction direction){
        externalRequest.add(new ExternalRequest(floor, direction));
    }
}

class Elevator{
    private int currentFloor = 1;
    private Direction direction = Direction.UP;
    private State state;
    private int maxFloor;
    private int minFloor;
    Elevator(int minFloor,int maxFloor){
        this.minFloor = minFloor;
        this.maxFloor = maxFloor;
    }
    public Elevator getElevatorIntance(int minFloor,int maxFloor){
        this.minFloor = minFloor;
        this.maxFloor = maxFloor;
        return this;
    }
    public int getCurrentFloor(){
        return currentFloor;
    }
    public void setCurrentFloor(int currentFloor){
        this.currentFloor = currentFloor;
    }
    public Direction getDirection(){
        return direction;
    }
    public void setDirection(Direction direction){
        this.direction = direction;
    }
    public State getState(){
        return state;
    }
    public void setState(State state){
        this.state = state;
    }
    public int getMaxFloor(){
        return maxFloor;
    }
    public int getMinFloor(){
        return minFloor;
    }
    public boolean isValidFloor(int floor){
        return floor<=getMaxFloor()&&floor>=getMinFloor();
    }
}

class Controller{
    private Elevator elevator;
    private RequestQueue queue;
    public Controller(){}
    public Controller(Elevator elevator,RequestQueue requestQueue){
        this.elevator = elevator;
        this.queue = requestQueue;
    }
    public Elevator getElevator(){
        return elevator;
    }
    public void setElevator(Elevator elevator){
        this.elevator = elevator;
    }
    public RequestQueue getQueue(){
        return queue;
    }
    public void setQueue(RequestQueue queue){
        this.queue = queue;
    }
    public void processRequest(){
        for(int i=0;i<queue.allRequest.size();i++){
            if (!queue.allRequest.get(i).matches("<\\d+(,\\w+)?>")) {
                queue.allRequest.remove(i);
                if(queue.allRequest.size()>1) i--;
            }
        }
        Integer tempI = null;
        ExternalRequest tempE = null;
        for(int i=0;i<queue.allRequest.size();i++){
            if(queue.allRequest.get(i).contains(",")) {
                int floor = Integer.parseInt(queue.allRequest.get(i).substring(queue.allRequest.get(i).indexOf('<') + 1, queue.allRequest.get(i).indexOf(',')));
                String direction = queue.allRequest.get(i).substring(queue.allRequest.get(i).indexOf(',')+1,queue.allRequest.get(i).indexOf('>'));
                ExternalRequest current = new ExternalRequest(floor, Direction.valueOf(direction));
                if (tempE == null ||!current.getFloor().equals(tempE.getFloor()) || current.getDirection() != tempE.getDirection()) {
                    queue.addExternalRequest(floor, Direction.valueOf(direction));
                    tempE = current;
                }
            }
            else {
                int floor = Integer.parseInt(queue.allRequest.get(i).substring(queue.allRequest.get(i).indexOf('<') + 1, queue.allRequest.get(i).indexOf('>')));
                if (tempI == null ||!tempI.equals(floor)) {
                    queue.addInternalRequest(floor);
                    tempI = floor;
                }
            }
        }
        for(int i = 0; i < queue.getExternalRequest().size(); i++) {
            if(!elevator.isValidFloor(queue.getExternalRequest().get(i).getFloor())) {
                queue.getExternalRequest().remove(i);
                i--;
            }
        }
        for(int i = 0; i < queue.getInternalRequest().size(); i++) {
            if(!elevator.isValidFloor(queue.getInternalRequest().get(i))) {
                queue.getInternalRequest().remove(i);
                i--;
            }
        }
    }
    public void determineDirection(){
        if(!queue.getInternalRequest().isEmpty()&&!queue.getExternalRequest().isEmpty()){
            if(elevator.getDirection().equals(Direction.UP)){
                if(internalDirection() || externalDirection()) elevator.setDirection(Direction.UP);
                else elevator.setDirection(Direction.DOWN);
            }
            else if(elevator.getDirection().equals(Direction.DOWN)){
                if(!internalDirection() || !externalDirection()) elevator.setDirection(Direction.DOWN);
                else elevator.setDirection(Direction.UP);
            }
            else elevator.setDirection(Direction.UP);
        }
        else if(queue.getInternalRequest().isEmpty()&&!queue.getExternalRequest().isEmpty()){
            Direction direction = externalDirection()?Direction.UP:Direction.DOWN;
            elevator.setDirection(direction);
        }
        else if(queue.getExternalRequest().isEmpty()&&!queue.getInternalRequest().isEmpty()){
            Direction direction = internalDirection()?Direction.UP:Direction.DOWN;
            elevator.setDirection(direction);
        }
    }
    public void move(){
        System.out.println("Current Floor: " + elevator.getCurrentFloor()+ " Direction: " + elevator.getDirection());
    }
    public boolean shouldStop(int floor){
        if(!queue.getInternalRequest().isEmpty()&&queue.getInternalRequest().getFirst() == elevator.getCurrentFloor()) return true;
        if(!queue.getInternalRequest().isEmpty()) return !queue.getExternalRequest().isEmpty()&&queue.getExternalRequest().getFirst().getFloor() == elevator.getCurrentFloor()&&queue.getExternalRequest().getFirst().getDirection().equals(elevator.getDirection());
        else return !queue.getExternalRequest().isEmpty()&&queue.getExternalRequest().getFirst().getFloor() == elevator.getCurrentFloor();
    }
    public void getNextFloor(){
        if(elevator.getDirection().equals(Direction.UP)&&elevator.getCurrentFloor()<elevator.getMaxFloor()) elevator.setCurrentFloor(elevator.getCurrentFloor()+1);
        else if(elevator.getDirection().equals(Direction.DOWN)&&elevator.getCurrentFloor()>elevator.getMinFloor()) elevator.setCurrentFloor(elevator.getCurrentFloor()-1);
    }
    public boolean internalDirection(){
        if(!queue.getInternalRequest().isEmpty()&&queue.getInternalRequest().getFirst() == elevator.getCurrentFloor()) {
            if (queue.getInternalRequest().size() == 2)
                return queue.getInternalRequest().get(1) > elevator.getCurrentFloor();
            else
                return elevator.getDirection().equals(Direction.UP);
        }
        return queue.getInternalRequest().getFirst() > elevator.getCurrentFloor();
    }
    public boolean externalDirection(){
        if(!queue.getExternalRequest().isEmpty()&&queue.getExternalRequest().getFirst().getFloor() == elevator.getCurrentFloor())
            return queue.getExternalRequest().getFirst().getDirection().equals(Direction.UP);
        return queue.getExternalRequest().getFirst().getFloor() > elevator.getCurrentFloor();
    }
    public void openDoor() {
            if (shouldStop(elevator.getCurrentFloor())) {
                System.out.println("Open Door # Floor " + elevator.getCurrentFloor()+"\nClose Door");
                removeRequest(elevator.getCurrentFloor());
            }
    }
    public void removeRequest(int currentFloor){
        if(!queue.getInternalRequest().isEmpty()&&queue.getInternalRequest().getFirst() == elevator.getCurrentFloor()) queue.getInternalRequest().remove(0);
        if(!queue.getExternalRequest().isEmpty()&&queue.getExternalRequest().getFirst().getFloor() == elevator.getCurrentFloor()) queue.getExternalRequest().remove(0);
    }
}
  1. 第三次迭代代码
点击查看代码
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        RequestQueue queue = new RequestQueue();
        int minFloor = scanner.nextInt();
        int maxFloor = scanner.nextInt();
        scanner.nextLine();
        while (true) {
            String ask = scanner.nextLine();
            if (ask.equalsIgnoreCase("end")) break;
            queue.allRequest.add(ask);
        }
        scanner.close();
        Elevator elevator = new Elevator(minFloor, maxFloor);
        Controller a = new Controller(elevator, queue);
        a.processRequest();
        while (!a.getQueue().getInternalRequest().isEmpty() || !a.getQueue().getExternalRequest().isEmpty()) {
            a.move();
            a.determineDirection();
            a.openDoor();
            a.determineDirection();
            a.getNextFloor();
        }
    }
}

enum Direction {
    UP, DOWN, IDLE;
}

enum State {
    MOVING, STOPPED;
}

class Passenger {
    private Integer sourceFloor = null;
    private Integer destinationFloor = null;

    Passenger() {
    }

    Passenger(Integer sourceFloor, Integer destinationFloor) {
        this.destinationFloor = destinationFloor;
        this.sourceFloor = sourceFloor;
    }

    Passenger(Integer destinationFloor) {
        this.destinationFloor = destinationFloor;
    }

    public Integer getSourceFloor() {
        return sourceFloor;
    }

    public void setSourceFloor(Integer sourceFloor) {
        this.sourceFloor = sourceFloor;
    }

    public Integer getDestinationFloor() {
        return destinationFloor;
    }

    public void setDestinationFloor(Integer destinationFloor) {
        this.destinationFloor = destinationFloor;
    }

    public Direction getDirection() {
        if (sourceFloor != null && sourceFloor > destinationFloor) return Direction.DOWN;
        else if (sourceFloor != null && sourceFloor < destinationFloor) return Direction.UP;
        return Direction.IDLE;
    }
}

class RequestQueue {
    private LinkedList<Passenger> internalRequest = new LinkedList<>();
    private LinkedList<Passenger> externalRequest = new LinkedList<>();
    LinkedList<String> allRequest = new LinkedList<>();

    public RequestQueue getQueueInstance() {
        return this;
    }

    public LinkedList<Passenger> getInternalRequest() {
        return internalRequest;
    }

    public void setInternalRequest(LinkedList<Passenger> internalRequest) {
        this.internalRequest = internalRequest;
    }

    public LinkedList<Passenger> getExternalRequest() {
        return externalRequest;
    }

    public void setExternalRequest(LinkedList<Passenger> externalRequest) {
        this.externalRequest = externalRequest;
    }

    public void addInternalRequest(Passenger passenger) {
        internalRequest.add(passenger);
    }

    public void addExternalRequest(Passenger passenger) {
        externalRequest.add(passenger);
    }
}

class Elevator {
    private int currentFloor = 1;
    private Direction direction = Direction.UP;
    private State state;
    private int maxFloor;
    private int minFloor;

    Elevator(int minFloor, int maxFloor) {
        this.minFloor = minFloor;
        this.maxFloor = maxFloor;
    }

    public Elevator getElevatorIntance(int minFloor, int maxFloor) {
        this.minFloor = minFloor;
        this.maxFloor = maxFloor;
        return this;
    }

    public int getCurrentFloor() {
        return currentFloor;
    }

    public void setCurrentFloor(int currentFloor) {
        this.currentFloor = currentFloor;
    }

    public Direction getDirection() {
        return direction;
    }

    public void setDirection(Direction direction) {
        this.direction = direction;
    }

    public State getState() {
        return state;
    }

    public void setState(State state) {
        this.state = state;
    }

    public int getMaxFloor() {
        return maxFloor;
    }

    public int getMinFloor() {
        return minFloor;
    }

    public boolean isValidFloor(int floor) {
        return floor <= getMaxFloor() && floor >= getMinFloor();
    }
}

class Controller {
    private Elevator elevator;
    private RequestQueue queue;

    public Controller() {
    }

    public Controller(Elevator elevator, RequestQueue requestQueue) {
        this.elevator = elevator;
        this.queue = requestQueue;
    }

    public Elevator getElevator() {
        return elevator;
    }

    public void setElevator(Elevator elevator) {
        this.elevator = elevator;
    }

    public RequestQueue getQueue() {
        return queue;
    }

    public void setQueue(RequestQueue queue) {
        this.queue = queue;
    }

    public void processRequest() {
        for (int i = 0; i < queue.allRequest.size(); i++) {
            if (!queue.allRequest.get(i).matches("<\\d+(,\\w+)?>")) {
                queue.allRequest.remove(i);
                if (queue.allRequest.size() > 1) i--;
            }
        }
        for (String req : queue.allRequest) {
            if (req.contains(",")) {
                Integer sourceFloor = Integer.parseInt(req.substring(req.indexOf('<') + 1, req.indexOf(',')));
                String floor = req.substring(req.indexOf(',') + 1, req.indexOf('>'));
                Passenger current = new Passenger(sourceFloor, Integer.parseInt(floor));
                queue.addExternalRequest(current);
            } else {
                int floor = Integer.parseInt(req.substring(req.indexOf('<') + 1, req.indexOf('>')));
                Passenger current = new Passenger(floor);
                queue.addInternalRequest(current);
            }
        }
        for (int i = 0; i < queue.getExternalRequest().size(); i++) {
            if (!elevator.isValidFloor(queue.getExternalRequest().get(i).getSourceFloor())) {
                queue.getExternalRequest().remove(i);
                i--;
            }
        }
        for (int i = 0; i < queue.getInternalRequest().size(); i++) {
            if (!elevator.isValidFloor(queue.getInternalRequest().get(i).getDestinationFloor())) {
                queue.getInternalRequest().remove(i);
                i--;
            }
        }
    }

    public void determineDirection() {
        if (!queue.getInternalRequest().isEmpty() && !queue.getExternalRequest().isEmpty()) {
            if (elevator.getDirection().equals(Direction.UP)) {
                if (internalDirection() || externalDirection()) elevator.setDirection(Direction.UP);
                else elevator.setDirection(Direction.DOWN);
            } else if (elevator.getDirection().equals(Direction.DOWN)) {
                if (!internalDirection() || !externalDirection()) elevator.setDirection(Direction.DOWN);
                else elevator.setDirection(Direction.UP);
            } else elevator.setDirection(Direction.UP);
        } else if (queue.getInternalRequest().isEmpty() && !queue.getExternalRequest().isEmpty()) {
            Direction direction = externalDirection() ? Direction.UP : Direction.DOWN;
            elevator.setDirection(direction);
        } else if (queue.getExternalRequest().isEmpty() && !queue.getInternalRequest().isEmpty()) {
            Direction direction = internalDirection() ? Direction.UP : Direction.DOWN;
            elevator.setDirection(direction);
        }
    }

    public void move() {
        System.out.println("Current Floor: " + elevator.getCurrentFloor() + " Direction: " + elevator.getDirection());
    }

    public boolean shouldStop(int floor) {
        if (!queue.getInternalRequest().isEmpty() && queue.getInternalRequest().getFirst().getDestinationFloor() == elevator.getCurrentFloor())
            return true;
        if (!queue.getExternalRequest().isEmpty() && queue.getExternalRequest().getFirst().getSourceFloor() == elevator.getCurrentFloor() && queue.getExternalRequest().getFirst().getDirection().equals(elevator.getDirection()))
            return true;
        return false;
    }

    public void getNextFloor() {
        if (elevator.getDirection().equals(Direction.UP) && elevator.getCurrentFloor() < elevator.getMaxFloor())
            elevator.setCurrentFloor(elevator.getCurrentFloor() + 1);
        else if (elevator.getDirection().equals(Direction.DOWN) && elevator.getCurrentFloor() > elevator.getMinFloor())
            elevator.setCurrentFloor(elevator.getCurrentFloor() - 1);
    }

    public boolean internalDirection() {
        if (!queue.getInternalRequest().isEmpty() && queue.getInternalRequest().getFirst().getDestinationFloor() == elevator.getCurrentFloor()) {
            if (queue.getInternalRequest().size() == 2)
                return queue.getInternalRequest().get(1).getDestinationFloor() > elevator.getCurrentFloor();
            else
                return elevator.getDirection().equals(Direction.UP);
        }
        return queue.getInternalRequest().getFirst().getDestinationFloor() > elevator.getCurrentFloor();
    }

    public boolean externalDirection() {
        if (!queue.getExternalRequest().isEmpty() && queue.getExternalRequest().getFirst().getSourceFloor() == elevator.getCurrentFloor())
            return queue.getExternalRequest().getFirst().getDirection().equals(Direction.UP);
        return queue.getExternalRequest().getFirst().getSourceFloor() > elevator.getCurrentFloor();
    }

    public void openDoor() {
        if (shouldStop(elevator.getCurrentFloor())) {
            System.out.println("Open Door # Floor " + elevator.getCurrentFloor() + "\nClose Door");
            removeRequest(elevator.getCurrentFloor());
        }
    }

    public void removeRequest(int currentFloor) {
        if (!queue.getInternalRequest().isEmpty() && queue.getInternalRequest().getFirst().getDestinationFloor() == currentFloor) {
            queue.getInternalRequest().removeFirst();
        }
        if (!queue.getInternalRequest().isEmpty()&&!queue.getExternalRequest().isEmpty() && queue.getExternalRequest().getFirst().getSourceFloor() == currentFloor && queue.getExternalRequest().getFirst().getDirection().equals(elevator.getDirection())) {
            Passenger temp = new Passenger(queue.getExternalRequest().getFirst().getDestinationFloor());
            queue.addInternalRequest(temp);
            queue.getExternalRequest().removeFirst();
        }
        else if(queue.getInternalRequest().isEmpty()&&!queue.getExternalRequest().isEmpty()&&queue.getExternalRequest().getFirst().getSourceFloor() == currentFloor){
            Passenger temp = new Passenger(queue.getExternalRequest().getFirst().getDestinationFloor());
            queue.addInternalRequest(temp);
            queue.getExternalRequest().removeFirst();
        }
    }
}
posted @ 2025-04-19 16:21  QQteam  阅读(65)  评论(0)    收藏  举报