电梯调度

一、 项目目的

  • 学习调度算法
  • 通过实现电梯调度,体会操作系统调度过程
  • 学习特定环境下多线程编程方法

二、开发工具

  • 开发环境:Chrome + Subline Text
  • 开发语言:JavaScript

三、术语表

术语

解释

呼梯信号

调度请求

并联控制

共用一套呼梯信号系统,把两台或多台规格相同的电梯并联起来控制

内呼梯按钮

电梯内部发出呼梯信号的按钮,只对单部电梯有效

外呼梯按钮

电梯外部发出呼梯信号的按钮,对所有并联控制的电梯有效

四、项目方案

1. 调度算法

(1) 内调度:LOOK算法

  • 原理:

LOOK算法是扫描算法的一种改进。扫描算法(SCAN)是一种按照楼层顺序依次服务请求的算法,它让电梯在最底层和最顶层之间连续往返运行,在运行过程中响应处在于电梯运行方向相同的各楼层上的请求。扫描算法较好地解决了电梯移动的问题,在这个算法中,每个电梯响应乘客请求使乘客获得服务的次序是由其发出请求的乘客的位置与当前电梯位置之间的距离来决定的,所有的与电梯运行方向相同的乘客的请求在一次电梯向上运行或向下运行的过程中完成,免去了电梯频繁的来回移动

对LOOK算法而言,电梯同样在最底层和最顶层之间运行。但当LOOK算法发现电梯所移动的方向上不再有请求时立即改变运行方向,而扫描算法则需要移动到最底层或者最顶层时才改变运行方向。

  • 实现:

    • 设置一个数组queue用来存放所有呼梯层
    • 每一层在queue中最多只允许重复出现3次,分别对应:内部呼梯信号、外部向上的呼梯信号以及外部向下的呼梯信号;为此,建立三个数组insideoutsideUpoutsideDown,三个数组的下标为楼层数,值表示是否是该种呼梯信号,1为是,空或者0为否。如:某人在10楼外部按了向上的按钮,即outsideUp[10] = 1;
    • 电梯的状态——是否运行中、运行方向,分别存放在变量runninggoingUp
    • 电梯每运行到一层,判断该层是否在queue中,如果在,再判断它的胡梯信号是否和运行方向一致或者是该方向中的最后一层,若是,打开电梯门,更新电梯状态,若不是,电梯保持运动方向运动,更新显示器数字。

    变量

    作用

    多部电梯时的变体(电梯数ELE_COUNT)

    queue[]

    存放所有呼梯层

    呼梯层号

    queue[ELE_COUNT][]

    inside[]

    判断是否是内部呼梯信号

    1或0或空

    inside[ELE_COUNT][MAX_FLOOR]

    outsideUp[]

    判断是否是外部向上的呼梯信号

    1或0或空

    outsideUp[ELE_COUNT][MAX_FLOOR]

    outsideDown[]

    判断是否是外部向下的呼梯信号

    1或0或空

    outsideDown[ELE_COUNT[MAX_FLOOR]

    currentFloor

    电梯当前运动到的楼层

    楼层号

    currentFLoor[ELE_COUNT]

    running

    判断电梯是否处于运动状态

    true或false

    running[ELE_COUNT]

    goingUp

    判断电梯运动方向是否为向上

    true或false

    goningUp[ELE_COUNT]

    timer

    每隔1s执行一次主函数

    timer[ELE_COUNT]

(2) 外调度:优先级调度算法

  • 原理:将到呼梯层时间最短的电梯优先级设为最高,优先执行,即只将该呼梯层加入到时间最短的电梯queue中。
  • 实现:
    • 运行经过楼层 = 停顿楼层 + 非停顿楼层
    • 运行时间 = 停顿楼层 * 停顿时间 + 非停顿楼层 * 电梯经过一层的时间

2. 程序界面

  • 初始界面

  • 运动界面

3. 具体实现

  • 主要函数说明

函数

功能

参数

返回值

dial(n, floor)

将呼梯层加入到第n部电梯的queue中

n: 电梯标号(从0开始); floor: 呼梯层号

run(n)

检测当前运动到的楼层需不需要停,并作出相应的反应

n: 电梯标号

updateState(n)

更新电梯状态:是否运行、运行方向

n: 电梯标号

  • 辅助函数说明

函数

功能

参数

返回值

init()

初始化所有变量

openDoor(n)

电梯停下后自动开启电梯门

n: 电梯标号

closeDoor(n)

关闭电梯门

n: 电梯标号

openDoorByButton(n)

电梯停下时手动开启电梯门

n: 电梯标号

updateFloorInfo(n)

更新楼层信息,包括:门的上下移动效果、显示屏的数字和上下状态灯的变化

n: 电梯标号

getMaxInQueue(n)

找出queue中的最大楼层数

n: 电梯标号

最大楼层

getMinInQueue(n)

找出queue中的最小楼层数

n: 电梯标号

最小楼层数

removeFromQueue(n, floor)

从queue中移除楼层

n: 电梯标号; floor: 被移除的楼层

betweenCount(a, b, n)

计算两个楼层间的需要停下的楼层数

a、b: 楼层区间端点; n: 电梯标号

[a,b]区间内的楼层数

  • 具体代码

    • 外调度

      // 点击事件的函数功能:将外部按钮的dial加入到其中一台电梯中
      // 算法:加入到离呼层最短时间的电梯中
      $(".goup").click(function(){
      var this_id = $(this).parent()[0].id; //只有通过id访问是一个元素,通过标签和class访问的是一个数组(元素列表)
      var pressedFloor = Number(this_id.substr(5)); //从下标为5的位置开始取
      if (isNaN(pressedFloor)) {
      ;
      }
      else {
      var minDistance = 2 * (MAX_FLOOR - MIN_FLOOR); // 可能出现的最大步数
      var distance = 0;
      var elevatorToPush = 0;
      // 希望在最短时间内达到呼层
      // 计算到呼层的步数(1s/步)+5s当中停下的楼层:
      // if没有运动 else:
      // if当前层在呼层的下面或当前层
      // 电梯向上运动
      // 电梯向下运动
      // else当前层在呼层的上面
      // 电梯向上运动
      // 电梯向下运动
      for (var i = 0; i < ELE_COUNT; i++) {
      if (!running[i]) {
      distance = Math.abs(pressedFloor - currentFloor[i]);
      }
      else {
      var minInQueue = getMinInQueue(i);
      var maxInQueue = getMaxInQueue(i);
      if (currentFloor[i] <= pressedFloor) {
      if (goingUp[i]) {
      distance =
      pressedFloor - currentFloor[i]
      + 5 * betweenCount(pressedFloor, currentFloor[i], i);
      }
      else {
      distance = currentFloor[i] - minInQueue + pressedFloor - minInQueue + 5 *
      betweenCount(minInQueue, pressedFloor, i);
      }
      }
      else {
      if (goingUp[i]) {
      distance = maxInQueue - currentFloor[i] + maxInQueue - minInQueue +
      Math.abs(minInQueue - pressedFloor) + 5 * betweenCount(minDistance, maxInQueue,
      i);
      }
      else {
      distance = currentFloor[i] - minInQueue + Math.abs(minInQueue - pressedFloor)
      + 5
      betweenCount(currentFloor[i], minInQueue, i);
      }
      }
      }
      if (distance < minDistance) {
      minDistance = distance;
      elevatorToPush = i;
      }
      }

          if (outsideUp[elevatorToPush][pressedFloor] != 1) {outsideUp[elevatorToPush][pressedFloor] = 1;dial(elevatorToPush, pressedFloor);$(this).addClass("on"); //改变上下按钮为白色}
      }
      

      });

      $(".godown").click(function(){
      var this_id = $(this).parent()[0].id;
      var pressedFloor = Number(this_id.substr(5));
      if (isNaN(pressedFloor)) {
      ;
      }
      else{
      var minDistance = 2 * (MAX_FLOOR - MIN_FLOOR); // 可能出现的最大步数
      var distance = 0;
      var elevatorToPush = 0;

          for (var i = 0; i < ELE_COUNT; i++) {if (!running[i]) {distance = Math.abs(currentFloor[i] - pressedFloor);}else {var minInQueue = getMinInQueue(i);var maxInQueue = getMaxInQueue(i);if (currentFloor[i] >= pressedFloor) {if (goingUp[i]) {distance = maxInQueue - currentFloor[i] + maxInQueue - pressedFloor + 5 *betweenCount(maxInQueue, pressedFloor, i);}else {distance = currentFloor[i] - pressedFloor + 5 * betweenCount(pressedFloor,currentFloor[i], i);}}else {if (goingUp[i]) {distance = maxInQueue - currentFloor[i] + Math.abs(maxInQueue - pressedFloor) + 5 * betweenCount(currentFloor[i], maxInQueue, i);}else {distance = currentFloor[i] - minInQueue + maxInQueue - minInQueue +Math.abs(maxInQueue - pressedFloor) + 5 * betweenCount(minDistance, maxInQueue,i);}}}if (distance < minDistance) {minDistance = distance;elevatorToPush = i;}}if (outsideDown[elevatorToPush][pressedFloor] != 1) {outsideDown[elevatorToPush][pressedFloor] = 1;dial(elevatorToPush, pressedFloor);$(this).addClass("on");}
      }http://www.biyezuopin.vip
      

      });

    • 内调度

      // 点击事件函数功能:将内部button的数字加入到该楼层中
      $(".dial .button").click(function(){
      var this_class = $(this)[0].className;
      var parent_id = $(this).parent()[0].id;
      var pressedFloor = Number(this_class.substr(11));
      var n = Number(parent_id.substr(7));
      console.log(“按下的楼层数为:”+pressedFloor);
      if (!isNaN(pressedFloor)) {
      if (inside[n][pressedFloor]!= 1) {
      inside[n][pressedFloor] = 1;
      dial(n, pressedFloor);
      $(this).addClass(“pressed”);
      }
      }
      });

    • 主要函数

      // 函数功能:检测当前运动到的楼层需不需要停并实现相应功能
      // 参数:第n部电梯(n从0开始)
      function run(n) {
      // if (DEBUG_MODE) {
      // console.log(“elevator:” + n + " running:"+running[n] + " goingUp:"+goingUp[n] + " queue:"+queue[n] + " previousFloor:"+currentFloor[n]);
      // }

      if(running[n]) { //已经升到currentFloor的状态NeedToStop[n] = false; // if elevator is right where it's calledif (queue[n].indexOf(currentFloor[n]) > -1) {    if (inside[n][currentFloor[n]] == 1) { lightsOff(n, currentFloor[n], INSIDE);removeFromQueue(n, currentFloor[n]);inside[n][currentFloor[n]] = 0;NeedToStop[n] = true;}if (goingUp[n]) { if (outsideUp[n][currentFloor[n]] == 1) {lightsOff(n, currentFloor[n], OUTSIDE_UP);removeFromQueue(n, currentFloor[n]);outsideUp[n][currentFloor[n]] = 0;NeedToStop[n] = true;}if (outsideDown[n][currentFloor[n]] == 1 && currentFloor[n] == getMaxInQueue(n)) {lightsOff(n, currentFloor[n], OUTSIDE_DOWN);removeFromQueue(n, currentFloor[n]);outsideDown[n][currentFloor[n]] = 0;NeedToStop[n] = true;} }else {if (outsideDown[n][currentFloor[n]] == 1) {lightsOff(n, currentFloor[n], OUTSIDE_DOWN);removeFromQueue(n, currentFloor[n]);outsideDown[n][currentFloor[n]] = 0;NeedToStop[n] = true;}if (outsideUp[n][currentFloor[n]] == 1 && currentFloor[n] == getMinInQueue(n)) {lightsOff(n, currentFloor[n], OUTSIDE_UP);removeFromQueue(n, currentFloor[n]);outsideUp[n][currentFloor[n]] = 0;NeedToStop[n] = true;}}http://www.biyezuopin.vipif (NeedToStop[n]) {if (timer[n])clearInterval(timer[n]);setTimeout(function(){openDoor(n);//4s后关门 3s后设置timer timer为1s(所以关门开门时间都是4s)setTimeout(function(){closeDoor(n);setTimeout(function(){timer[n] = setInterval("run("+n+")", 1000);}, 2000);}, 2000);}, 1000); // NeedToStop[n] = false;        }else {goingUp[n] ? moveUp(n) : moveDown(n);}}else {goingUp[n] ? moveUp(n) : moveDown(n);}updataStatus(n);
      }updateFloorInfo(n);
      

      }

五、总结

  • 外部的调度还有待完善的地方。在计算上,运行时间和停下时间是接近于真实值的不准确的值,这是我的算法的问题;其次,放在实际生活中,停下的时间并不是单次开门关门时间的累加,而要考虑许多其他原因,比如人流强度。

  • 代码优化不够。代码在某种程度上看起来比较混乱,可读性不高。

  • 整个设计流程反思:一开始应该着眼整体、全局,构思好大体的框架而不是边写代码边构思,后者导致开发效率显著降低。

基于JavaScript的电梯调度设计相关推荐

  1. 基于JavaScript网上商城开发设计 毕业设计-附源码261620

    Node.js网上商城的开发 摘  要 随着Internet的使用越来越广泛,在传统的商业模式中,对于日常各类商品,人们习惯于到各种商家店铺购买.然而在快节奏的新时代中,人们不一定能为购买各类商品腾出 ...

  2. 单片机c语言电梯楼层,基于单片机五层电梯课程设计.pdf

    课程设计报告 课程名称 微机课程设计 设计题目 电梯模拟运行设计 专业班级 自动化1041 姓 名 王 会 学 号 1004421122 指导教师 刘文洲 蔡长青 起止时间 2013.12.23201 ...

  3. 面向对象的程序设计-电梯调度系统的设计、优化与测试

    面向对象的程序设计(2019)第二单元总结 I  对问题的初体验 在开始OO之旅前,对OO电梯早有耳闻.这一次终于轮到我自己实现OO电梯了.首先从顶层需求出发对电梯系统进行分析,对象包括电梯.任务和乘 ...

  4. java面向对象模拟电梯_面向对象的程序设计-电梯调度系统的设计、优化与测试...

    面向对象的程序设计(2019)第二单元总结 I  对问题的初体验 在开始OO之旅前,对OO电梯早有耳闻.这一次终于轮到我自己实现OO电梯了.首先从顶层需求出发对电梯系统进行分析,对象包括电梯.任务和乘 ...

  5. 基于单片机的电梯控制系统研究内容及设计步骤

    本课题的主要任务就是完成一个电梯系统的调度模块 ,即根据每个楼层不同 顾客的按键需求 ,让电梯做出合理的判断 ,正确高效地知道电梯完成各项载客任 务.根据此任务,本课题需要研究的内容有: 1.根据系统 ...

  6. 结对项目开发电梯调度 - 整体设计

    一.系统介绍 1. 功能描述 本电梯系统用来控制一台运行于一个具有16层的大楼电梯,它具有上升.下降.开门.关门.载客的基本功能. 大楼的每一层都有: (1) 两个指示灯:  这两个指示灯分别用于指示 ...

  7. 基于8086简易电子琴系统仿真设计-基于8086红外自动门控制系统设计-基于单片机8x8矩阵键盘两机串口通信-基于单片机8层电梯控制系统仿真设计-基于单片机ADC0809和DAC0832模数和数模设计

    1189基于8086简易电子琴系统仿真设计-设计资料 编写一实现电子琴的程序,并实现若干扩展功能. 基本功能:用键盘输入对应的七个音阶,通过实验箱的喇叭发出声音,并通过七段数码管显示输入音阶: 扩展功 ...

  8. android电梯程序设计,课内资源 - 基于Android实现的电梯调度模拟

    一.使用说明 1.1 项目简介 某一楼有20层,操作者可以通过使用5部电梯从起始楼层来到达指定的楼层.本项目通过实现电梯调度,来模拟实现操作系统的调度过程,并且学习Android环境下使用Java的多 ...

  9. android电梯程序设计,[源码和文档分享]基于Android实现的电梯调度模拟

    一.使用说明 1.1 项目简介 某一楼有20层,操作者可以通过使用5部电梯从起始楼层来到达指定的楼层.本项目通过实现电梯调度,来模拟实现操作系统的调度过程,并且学习Android环境下使用Java的多 ...

最新文章

  1. php 2 往数据库添加数据
  2. 建议收藏,清华高材生准备的90条Python程序建议
  3. Day19-File操作-创建 删除,文件过滤
  4. 我对CTO的理解 CTO要有技术魅力
  5. parted磁盘分区与GPT
  6. Maven Jrebel 多模块热部署方案
  7. windows linux 通过SSH X11Forwrding 使用图形化界面
  8. python3.5.3下载安装教程_在Python3.5下安装和测试
  9. YUI事件体系之Y.Do
  10. php代码怎么修改成laravel,Laravel框架实现即点即改功能的方法分析
  11. 搜索引擎背后的原理和中文日志检索
  12. java + testng wsdl 测试_在测试中使用XPATH断言的策略
  13. 出售 Mac 时做好哪些准备?
  14. FoneDog Toolkit iOS Data Recovery如何从iPhone恢复已删除的数据
  15. 兔子的烦恼(一)【NYOJ】
  16. [工具]TS 视频合并工具
  17. java笔试中易考的概念
  18. [转] Photoshop教程8000例
  19. Xcode 常用编译选项设置【推荐】
  20. Hive HBase

热门文章

  1. 基于多种分类方式的新闻文本种类预测[2021论文附代码]
  2. Java菜单(菜单条、菜单和菜单项)
  3. 股神巴菲特忠告中国股民:学会这几点,你离短线炒股的成功就不远了!
  4. ORers‘ Bling Chat | 【高光聊天记录集锦-03】:运小筹读者群里那些热烈的讨论
  5. Java获取12306余票信息(一)
  6. 常见面试题 -- JAVA 小结
  7. 【创新项目实训】Android移动开发教学app案例之音频播放器(二)
  8. centos系统性能监控常用软件介绍
  9. 文献--Bacterial coexistence driven by motility and spatial competition-模型代码
  10. Nginx中文域名配置