结对成员: 杨鹏飞(193) 邓嘉(164)

老师给定的电梯调度程序是一个C#命令行程序,其中电梯调度算法是第一次结对编程时我们自己编写的。

电梯调度要求的博文地址:http://www.cnblogs.com/xinz/archive/2012/10/08/2715076.html

由于程序运行时会打印电梯调度的相关信息,于是我想到了利用这些信息作为UI的驱动(如下图)。

不过对于几乎没有编写GUI界面经验的我来说,一个静态的UI界面就是一个非常大的挑战,更别说是一个动态演示电梯调度的UI程序了。

经过一番查询,发现可以利用管道来获取命令行程序的标准输入与输出,可是用什么程序来编写呢?这可难倒了我,后来综合考虑到管道实现、文本处理及UI设计,选择了使用Python这门脚本语言来完成UI程序,其中采用的UI库为安装Python 3.3.0时自带的tkinter。

由于动画式的演示实现起来相对困难,所以决定只展示每部电梯在每一个时刻(Tick)的运行状况,包括高度、楼层、电梯中的人数和已送达人数。

下面说明一下实现的具体过程。实现环境:Windows7 SP1 + Python 3.3.0

1、利用tkinter搭建界面。

首先需要调用tkinter模块:

from tkinter import *

然后绘制界面,电梯部分的代码省略:

复制代码
app = Tk()
app.title("电梯调度演示 V1.0.0.093 BUAA SCSE")
app.geometry('500x350')
Label(app,text="请输入Loader目录下的电梯xml文件:").pack()
elev = Entry(app)
elev.pack()
Label(app,text="请输入Loader目录下的乘客xml文件:").pack()
pg = Entry(app)
pg.pack()
Button(app,text="获取资源文件",command = saveinfo,width = 12).pack(pady = 3)
Button(app,text="开始演示",command = run,width = 12).pack(pady = 3)
Button(app,text="暂停5秒",command = pause,width = 12).pack(pady = 3)
复制代码

效果如下:

2、利用管道获取电梯调度程序的标准输入和输出。所以之前需要对项目进行编译并生成exe可执行文件。代码如下:

复制代码
import subprocess
r = subprocess.Popen("World\\bin\\Debug\\world.exe Loader\\" + elev.get() + " Loader\\" + pg.get(),stdin = subprocess.PIPE,stdout = subprocess.PIPE,stderr = subprocess.PIPE,shell = False)
info = str(r.stdout.read())
file = open('elev.txt','w')
file.write(info.replace(r'\r\n','\n'))
file.close()
复制代码

 

3、通过循环处理所得的elev.txt文件,实时更新界面,展示电梯的调度情况。

file = open('elev.txt','r')
for line in file:
    if line.startswith("Tick #):
        ......
    elif
        ......

同时,每一个Tick完成后暂停一段时间,让人能够观察到状态的变化。程序中,使用参数speed来调节。代码如下:

复制代码
import time

speed = 0.1

file = open('elev.txt','r')
for line in file:
    if line.startswith("Tick #"):
        ......
        app.update()
        time.sleep(speed)
......
复制代码

所有实时更新的变量(如电梯的高度、楼层等)都保存在StringVar的对象中,采用set方法来动态赋值。如下,展示当前时间和最终平均时间的变量avg:

avg = StringVar()
avg.set("当前时间(Tick):0,平均到达时间为:暂未完成!")
Label(app, textvariable = avg).pack()

实现总结:

1、最终的代码都写在项目根目录下的elev.py中,代码的行数为187行(包括空行):

2、运行方法:

运行方法: 1、安装Python 3.3.0及其以上版本。 2、将Python程序放在电梯调度程序主目录下,即项目文件所处目录。 3、使用VS2012打开电梯调度项目,采用Debug模式编译并生成可执行文件。 4、使用文本编辑器打开elev.py,调整speed的值,改变演示速度。 5、使用IDLE或命令行打开电梯调度程序,填写Loader目录下的电梯及乘客的XML文件。例如elevators.xml,passenger1.xml。 6、点击“获取资源文件”按钮,会生成elev.txt文件。 7、点击“开始演示”按钮,即可开始演示。 8、点击“暂停5秒”按钮,程序会暂停五秒。

注意事项: 1、elev.py必须放在主目录下,与Elevator、Passenger、Schedule等目录处于同一层次。 2、务必保证可以通过路径World\bin\Debug\world.exe调用电梯调度程序! 3、本程序只能演示给定的电梯调度算法、电梯及乘客的状态,无法控制电梯的运行!

3、运行截图:

elevators.xml描述如下:

复制代码
<?xml version="1.0" encoding="utf-8" ?>

<elevators 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns="http://tempuri.org/Elevators.xsd">
    
    <elevator id="0" capability="800" floorheight="10" highestfloor="20" initheight="0"/>
    <elevator id="1" capability="800" floorheight="10" highestfloor="20" initheight="20"/>
    <elevator id="2" capability="1600" floorheight="10" highestfloor="20" initheight="0"/>
    <elevator id="3" capability="2000" floorheight="10" highestfloor="20" initheight="20"/>
</elevators>
复制代码

 

(1)实例1,elevators.xml和passenger1.xml。

passenger1.xml如下,乘客数量为20:

复制代码
<?xml version="1.0" encoding="utf-8" ?>

<passengers
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns="http://tempuri.org/passengers.xsd">
  <passenger name="Sen_1" comingtime="148" fromfloor="15" tofloor="12" weight="63" />
  <passenger name="Sen_2" comingtime="144" fromfloor="3" tofloor="14" weight="67" />
  <passenger name="Sen_3" comingtime="290" fromfloor="17" tofloor="11" weight="62" />
  <passenger name="Sen_4" comingtime="273" fromfloor="17" tofloor="1" weight="64" />
  <passenger name="Sen_5" comingtime="204" fromfloor="6" tofloor="9" weight="51" />
  <passenger name="Sen_6" comingtime="50" fromfloor="12" tofloor="5" weight="57" />
  <passenger name="Sen_7" comingtime="67" fromfloor="3" tofloor="13" weight="66" />
  <passenger name="Sen_8" comingtime="241" fromfloor="9" tofloor="16" weight="52" />
  <passenger name="Sen_9" comingtime="160" fromfloor="3" tofloor="19" weight="66" />
  <passenger name="Sen_10" comingtime="27" fromfloor="3" tofloor="16" weight="61" />
  <passenger name="Sen_11" comingtime="199" fromfloor="16" tofloor="18" weight="108" />
  <passenger name="Sen_12" comingtime="189" fromfloor="15" tofloor="17" weight="100" />
  <passenger name="Sen_13" comingtime="271" fromfloor="17" tofloor="13" weight="91" />
  <passenger name="Sen_14" comingtime="129" fromfloor="13" tofloor="16" weight="114" />
  <passenger name="Sen_15" comingtime="143" fromfloor="1" tofloor="10" weight="85" />
  <passenger name="Sen_16" comingtime="156" fromfloor="18" tofloor="2" weight="95" />
  <passenger name="Sen_17" comingtime="15" fromfloor="5" tofloor="3" weight="108" />
  <passenger name="Sen_18" comingtime="274" fromfloor="4" tofloor="14" weight="96" />
  <passenger name="Sen_19" comingtime="156" fromfloor="16" tofloor="12" weight="89" />
  <passenger name="Sen_20" comingtime="213" fromfloor="10" tofloor="18" weight="93" />
</passengers>
复制代码

 

演示中截图

演示结果

(2)实例2,elevators.xml和passenger3.xml。

passenger3.xml如下,乘客数量为1000:

复制代码
<?xml version="1.0" encoding="utf-8" ?>

<passengers
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns="http://tempuri.org/passengers.xsd">
  <passenger name="Ben_1" comingtime="1788" fromfloor="18" tofloor="0" weight="63" />
  <passenger name="Ben_2" comingtime="2685" fromfloor="4" tofloor="1" weight="48" />

    ......

  <passenger name="Xiao_993" comingtime="3210" fromfloor="10" tofloor="7" weight="78" />
  <passenger name="Xiao_994" comingtime="576" fromfloor="16" tofloor="10" weight="100" />
  <passenger name="Xiao_995" comingtime="494" fromfloor="19" tofloor="5" weight="111" />
  <passenger name="Xiao_996" comingtime="1241" fromfloor="6" tofloor="11" weight="89" />
  <passenger name="Xiao_997" comingtime="1536" fromfloor="5" tofloor="16" weight="108" />
  <passenger name="Xiao_998" comingtime="1975" fromfloor="11" tofloor="13" weight="108" />
  <passenger name="Xiao_999" comingtime="760" fromfloor="5" tofloor="13" weight="106" />
  <passenger name="Xiao_1000" comingtime="53" fromfloor="19" tofloor="12" weight="91" />
</passengers>
复制代码

 

演示中

结果

 收获:

这次结对编程的最大收获就是管道的应用,无需对原项目做任何修改即可实现UI程序。相比开始使用动态链接库等想法,实在简便多了。同时,这也是我第一次使用Python编写GUI,对非常喜欢Python的我无疑是一次巨大的鼓励。最后,感谢所有提供帮助的人!

posted on 2013-01-09 12:25  邓嘉  阅读(506)  评论(1编辑  收藏  举报