机票管理系统(python3)
一、问题分析
问题分析:从数据的逻辑结构、数据存储以及对数据的操作三个方面出发分析。各数据的关系是集合;数据存在文件之中,在内存中用对象数组来存储;涉及对数据的增删改查以及排序等操作。
解题思路:将所有已有信息存储在文件中,当需要用的时候提取到对象数组中,而后对这个数组进行相应的操作。将客户或者管理员的操作封装到类中,通过实例化类的对象进而调用类中的方法,从而实现相应的操作。
开发方式:选择python语言,采用面向对象的开发方式。
二、主要难点分析与解决方案
1.文件操作
读:通过对文件进行从第二行开始读取,将一行的信息存储到一个对象中,然后将此对象放到数组中,形成对象数组,再进行下一步的操作。
写:将对象数组里的每个属性按照规定的顺序写入文件中,并确保每个对象一行。
file = open(".vscode\\keshe\\tickets.txt", "r", encoding='utf-8')
file.readline()
for line in file:
if line != '\n':
lines = line.strip('\n').split(" ")
obj = Ticket(lines[0], lines[1], lines[2], lines[3], lines[4], lines[5], lines[6], lines[7], lines[8], lines[9], lines[10], lines[11])
data.append(obj)
file.close()
file = open(".vscode\\keshe\\tickets.txt", "w", encoding='utf-8')
ile.write('航班编号 航空公司名称 起飞时间 起飞地点 降落时间 降落地点 余票 票价 经停站1名称 到达经停站1时间 经停站2名称 到达经停站2时间\n')
for x in data:
file.write('%s\n' %(x.id + ' ' + x.company_name + ' ' + x.takeoff_time + ' ' + x.takeoff_place+ ' ' + x.land_time + ' ' + x.land_place + ' ' + str(x.number) + ' ' + x.price + ' ' + x.stop1_place + ' ' + x.stop1_time +' '+ x.stop2_place +' '+ x.stop2_time))
print('机票购买成功!')
file.close()
2.航班动态管理
当航班被推迟或取消时,要通知已经买该票的乘客,此处我选用了用发邮件的方式。
import smtplib
from email.mime.text import MIMEText
from email.utils import formataddr
def send(email, message):
my_sender = '2963876107@qq.com'; my_pass = 'jeolzcecdirldffd' # QQ邮箱中 POP3/SMTP服务的验证码
my_user = email
def mail():
ret = True
try:
msg = MIMEText(message, 'plain' ,'utf-8')
msg['From'] = formataddr(["航空公司管理员",my_sender])
msg['To'] = formataddr(["顾客",my_user])
msg['Subject'] = email
server = smtplib.SMTP_SSL("smtp.qq.com", 465)
server.login(my_sender, my_pass)
server.sendmail(my_sender,[my_user,],msg.as_string())
server.quit()
except Exception:
ret = False
return ret
ret = mail()
if ret: print("邮件发送成功")
else: print("邮件发送失败") ret=False
return ret
3.预约抢票功能
当用户所要购买的机票没有余票时,可以进行预约抢票;当有人退订该机票时,则按预约先后顺序进行抢票。
利用数据结构中队列的思想,即先进先出的原则:当有多个人进行预订的时候,按预订的先后顺序写入文件中;当有人退订后,只把机票预订文件中所存的第一个人的信息取出并分配机票。
4.查询结果排序
排序有几种复杂度为O(nlogn)级别的算法,包括:堆排、归并、快排等,这里我选择归并排序。具体使用过程后面单独介绍。
三、实验方案及实现
1.主要类的设计与实现
1.1.CUSTOMER、Ticket、Reserve、Infor 仅作为对象容器使用
设计这些类的目的是:将存储数据的文件按行存到相应类类型的对象数组中,便于后续的各种操作。
class CUSTOMER: # 该类仅作为数据存储结构(类实例化对象后的容器作用)使用;方便读写customers.txt文件到列表中
def __init__(self, name, account, password, email, had, reserved):
self.name = name; self.account = account; self.password = password
self.email = email; self.had = had; self.reserved = reserved
class Reserve: # 机票预订类,包括预订者的账户,以及机票的航班号
def __init__(self, account, id):
self.account = account; self.id = id
class Ticket: # 机票类,包括机票的各种信息
def __init__(self, id, company_name, takeoff_time, takeoff_place, land_time, land_place, number, price, stop1_place, stop1_time, stop2_place, stop2_time):
self.id = id; self.company_name = company_name; self.takeoff_time = takeoff_time
self.takeoff_place = takeoff_place; self.land_time = land_time; self.land_place = land_place
self.number = number; self.price = price; self.stop1_place = stop1_place
self.stop1_time = stop1_time; self.stop2_place = stop2_place; self.stop2_time = stop2_time
class Infor: # 通知类,用于存储所要通知者的姓名和邮箱,便于发消息通知
def __init__(self, name, email):
self.name = name; self.email = email
1.2.Monitor
管理员对象,具有对航班进行增删改查以及推迟航班等特殊操作。
class Monitor:
def query(self):...
def add(self):...
def delete(self):...
def change(self):...
def late(self):...
1.3.Customer
顾客对象,具有查询航班,购买、预订、退订机票等操作。
class Customer:
def __init__(self, account, password):
self.account = account; self.password = password
def buy(self):...
def Reserve(self, ticket_id):...
def reserve(self):...
def cancel(self):...
2.其他功能函数
顾客登录身份验证以及新用户的注册。
def load():... def regist():...
专门用来处理时间(将存储的时间格式转换为月日时分的格式,便于展示)。
def time_trans(time):... def Print(args):...
若顾客的查询结果有多个则分别按不同的依据进行排序。
def recommend(data):... def sort_price(data): def sort_time(data): def sort_number(data):
当航班被推迟或取消时,用来通知已经买票的乘客(以邮件的形式),并向其推荐同出发降落地点且未延迟的最近航班。
def infor(ticket_id, Type, qifei): def info(Type, qifei): def send(email, message):
def recommend(takeoff_place, land_place, takeoff_time, land_time):
3.主函数
3.1.客户端程序
if __name__=="__main__":
print('* * * * * * * * * 机票管理系统 * * * * * * * * *')
a = input('请登录或注册:1、登录 2、注册 ->> ')
if a == '1': customer01 = load()
else: regist(); customer01 = load()
while(1):
behavior = input('选择后续操作:1.航班查询 2.机票购买 3.预约机票 4.退订机票 ===> ')
if behavior == '1': customer01.query()
elif behavior == '2': ticket_id = customer01.buy()
if ticket_id != 0:
b = int(input('票已经被抢够完,是否去预约抢票:1、预约抢票 2、离开 ->> '))
if b == 1: customer01.Reserve(ticket_id)
elif behavior == '3': customer01.reserve()
elif behavior == '4': customer01.cancel()
else: print('输入有误.....')
3.2.管理端程序
if __name__ == "__main__":
print('* * * * * * * * * 机票管理系统 * * * * * * * * *')
monitor01 = Monitor()
while(1):
behavior = input('选择后续操作:1.查询航班 2.增加航班 3.删除航班 4.修改航班 5.推迟航班 ===> ')
if behavior == '1': monitor01.query()
elif behavior == '2': monitor01.add()
elif behavior == '3': monitor01.delete()
elif behavior == '4': monitor01.change()
elif behavior == '5': monitor01.late()
else: print('输入有误.....')
4.存储文件
4.1.ticket.txt存储机票信息
航班编号 | 航空公司名称 | 起飞时间 | 起飞地点 | 降落时间 | 降落地点 | 余票 | 票价 | 经停站1名称 | 到达经停站1时间 | 经停站2名称 | 到达经停站2时间
4.2.customer.txt存储顾客信息
姓名 | 账号 | 密码 | 邮箱 | 已到手的机票 | 已预订的机票
4.3.reserve.txt存储机票预订相关信息
用户账号 | 航班编号
4.4.info_1.txt和info_2.txt存储要通知的客户信息
姓名 | 邮箱
四、排序算法设计
归并排序有两个缺点:1.当所要排序的集合中的元素个数很少时,算法多数时间消耗在递归的处理上;2.辅助数组的使用增加了算法的空间,且每次调用merge时,都需要将B复制回A中,消耗了时间。尤其是当所要排序的数组是对象数组时,每次复制数组中的元素都要花费更长的时间。
解决办法:当子集合的元素个数适当少时,采用在小规模集合上能有效工作的插入排序算法而非继续划分;用一个链接数组LINK代替B,LINK中的元素为A中元素的下标,它表示下一个元素所在的下标位置。规定当LINK中元素为0时表明后面不再有某下标下的A元素值大于当前下标下的A元素值,即为当前排序范围内的最大值。
选择对已经选出的符合条件的航班按价格进行排序作为例子:
def sort_price(data):
link = [i for i in range(0, len(data))]
low = 1; high = len(data) - 1
p = merge_sort1(data, link, low, high)
while p != 0:
Print(data[p])
p = link[p]
采用优化的插入排序处理递归出口,即对短长度的对象数组排序。
def insert_sort(data, link, low, high):
link[low] = 0; temp = low; p = low
for j in range(low+1, high+1):
k = p
if data[j].price <= data[p].price:
link[j] = p; p = j
while (data[j].price > data[k].price and (k != temp)) :
if data[j].price > data[link[k]].price:
k = link[k]
else:
r = link[k]; link[k] = j; link[j] = r; k = r
if data[j].price > data[temp].price:
link[temp] = j; link[j] = 0; temp = j
return p
优化的归并排序,当data的规模小于6时,用插入排序处理。
def merge_sort1(data, link, low, high):
if high - low + 1 < 6:
return insert_sort(data, link, low, high)
else:
mid = (low + high) // 2
q = merge_sort1(data, link, low, mid)
r = merge_sort1(data, link, mid + 1, high)
return merge1(data, link, q, r)
将已经排好序的两个子序列合并。
def merge1(data, link, q, r):
i = q; j = r; k = 0
while (i != 0) and (j != 0):
if data[i].price <= data[j].price:
link[k] = i; k = i; i = link[i]
else:
link[k] = j; k = j; j = link[j]
if i == 0: link[k] = j
else: link[k] = i
p = link[0]
return p
五、编程与程序清单
1.源程序文件名清单
Class.py 存放CUSTOMER、Ticket、Reserve、Infor四个容器类
customer.py Customer类的实现以及顾客端操作
monitor.py Monitor员类的实现以及管理端操作
ticket.txt 存储机票信息
customer.txt 存储顾客信息
reserve.txt 存储机票预订相关信息
info_1.txt 存储航班延期要通知的客户
info_2.txt 存储航班取消要通知的客户
2.引入包介绍
from Class import CUSTOMER, Infor, Ticket # 获取到对象类
import datetime # 获取系统当前时间
import smtplib # python邮件操作所需
from email.mime.text import MIMEText
from email.utils import formataddr
六、测试方法、测试数据与测试结果
1.测试方法与测试数据
首先自行编制虚拟并满足要求的测试数据,存到相应的存储文件中(之前介绍的)。
此次课设并没有涉及可视化界面,而是通过与系统在终端进行交互的方式进行测试。因此在测试时设置了while循环(始终为真),可实现一直测试的效果。
1.1.客户端
通过预制好模拟所用的数据,包括已注册客户的信息和航班信息等,模拟用户登录而后进行相应操作的过程。注意的是必须通过客户信息验证之后才能创建客户对象,进而进行接下来的操作。
a = input('请登录或注册:1、登录 2、注册 ->> ')
if a == '1': customer01 = load()
else: regist(); customer01 = load()
while(1):
behavior = input('选择后续操作:1.航班查询 2.机票购买 3.预约机票 4.退订机票 ===> ')
if behavior == '1': customer01.query()
elif behavior == '2': ticket_id = customer01.buy()
if ticket_id != 0:
b = int(input('票已经被抢够完,是否去预约抢票:1、预约抢票 2、离开 ->> '))
if b == 1: customer01.Reserve(ticket_id)
elif behavior == '3': customer01.reserve()
elif behavior == '4': customer01.cancel()
else: print('输入有误.....')
1.2.管理端
完善的话应该管理员在进行登录时也应当进行验证,但此验证操作与客户的登录验证毫无差别,所以在管理端并没有登录操作,而是直接创建管理员对象,进行操作。
monitor01 = Monitor()
while(1):
behavior = input('选择后续操作:1.查询航班 2.增加航班 3.删除航班 4.修改航班 5.推迟航班 ===> ')
if behavior == '1': monitor01.query()
elif behavior == '2': monitor01.add()
elif behavior == '3': monitor01.delete()
elif behavior == '4': monitor01.change()
elif behavior == '5': monitor01.late()
else: print('输入有误.....')
2.测试结果
2.1.客户端
终端输出操作信息的同时相应的文件也作出对应的改变。
2.2.管理端
七、程序的使用说明
需使用Python3.0以上的编译器,python2.x编译因语法差异不通过。
当程序提示输入操作所对应的数字时,尽量不要输入未提示的数字。
在输入城市、机票等信息时,不要加空格。
因为航线以及城市过多,不能保证虚构航行数据与现实一致。
八、项目完整代码
https://download.csdn.net/download/guangluo/12283142
不需积分,下载即可