12307 火车票购买平台
大二课程数据库原理的期末项目。有查票、中转、订票、余票查询、线路管理等等功能。后端使用了 Flask 框架,前端使用了 Vue。项目最终获得了满分。
12307 是我第一次制作前端页面。之前写 WannaAC (上一篇博客) 的时候涉及过一点点,不过它只有单页面,也就是一张表格、一个输入框的难度。这次的前端涉及到页面路由、按钮交互、身份验证、后端 API 调用等等…… 所以我花了点时间在研究 Vue 框架上。
我平常比较喜欢简单整洁的界面,这次用 ElementUI 实现的网页样式就是我心仪的设计风格。
订票页面
Vue 提倡将重复元素抽象成组件以方便复用。我绘制了一个 “火车票组件”,并且在查看订单的页面上放了几张「真的火车票」。比起显示一堆文字,这样感觉上更直观。
查看订单
Work From Home
制作这个项目的时候正好是 Covid-19 新型冠状病毒爆发的疫情期间,学校在线教学,我和队友 @macromogic 也是在线上完成了项目的合作。一个月来,基本上每天晚上都用腾讯会议开屏幕共享一起写代码。
线上做项目其实也很有意思,我们强迫自己练习了 Git 的各种使用技巧。比如 rebase
,fast-forward
,还有 git -f
😅。
后来才知道这其实就是敏捷开发里 “结伴编程” 的雏形。选一个好队友真的非常重要。后续我们一起合作了嵌入式、面向对象、计算机网络、操作系统、软件工程的期末项目。
ORM
ORM 是加分项。但其实像票务系统这种表关系复杂的数据库,个人是不赞同过度 ORM 的。
何时不使用 ORM
比如在火车票余票查询过程中,我们要在一个查询中实现的逻辑有:
- 从起点到终点有直达的火车班车
- 在这样一趟列车中,是否存在一个座位,它从起点到终点的每个区间都可预定
这个描述翻译成 SQL 就是 7~8 张表的联合查询。如果翻译成 ORM,就是接下来长达一整个屏幕的、眼花缭乱、难以维护的代码。
使用 ORM 查询余票信息
中转火车
查询中转列车应该怎么设计算法?看起来我们只需要跑一个最短路算法查询,就可以得到结果。如果提前跑好最短路,将方案存储成为 [车站数 * 车站数] 的方阵,应该是可行的算法。
实际查询比想象的方案复杂。中转的次数要尽可能低。中转的等待时间要尽可能少。车票的价格要尽可能的低。这已经成为一个没有最优解的多目标优化问题。加上中铁经常调整火车调图(停运或增运列车),各线路客流量有区别,设计一个动态优秀的中转算法是非常困难的。
我们的设计加入了一点启发式搜索。因为中转通常发生在客流量较大的城市枢纽站,所以我们按照客流量动态提升大型枢纽站的权重。为了进一步提升搜索速度,我们在最短路算法中不会从小站出发进行边集拓展。经过这样的优化,我们的中转火车算法总体上令人满意。
轶事
2021 年上半年,我偶然收到一封邮件,内容是询问我这个项目(开源在 GitHub 上)如何启动。仔细一查,竟然是一个外校学生想用这个项目充当他的毕业设计……
由于这个项目是两个大二学生的期末作业,所以还有非常多可以优化的部分。如果你对于火车订票系统有兴趣,我们可以一起讨论。如果你喜欢这篇博客,可以通过 RSS 订阅更新。欢迎关注我的 GitHub 和推特账号,我将分享更多有趣的优质内容。如果你对这篇文章有任何疑问或建议,请在下方留言。再会~
© LICENSED UNDER CC BY-NC-SA 4.0