结对成员: 杨鹏飞(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的我无疑是一次巨大的鼓励。最后,感谢所有提供帮助的人!