天天看點

購票系統設計之餘票處理标題購票系統設計之餘票處理

标題購票系統設計之餘票處理

一、前言

鐵路12306,對于所有人來說是非常熟悉。早些年,經常是一到發票時間,系統就自然崩潰了,讓無數人痛罵不止,最終無奈向黃牛低頭。最後,阿裡程式猿忍不住了,伸出了可愛的小手,無償幫鐵路12306重新優化設計系統,才有了現在的鐵路12306。

作為一名程式猿,當然想試一下水,看看其中的難度有多大。很有自知之明,避開了幾億使用者這一送命題,就簡單做個demo,實作一下基本的買票購票功能。

二、根據現有系統推測功能

一般來說,購票流程應該是這樣:

1. 選擇兩個站點,輸入兩個開始時間和結束時間,查詢對應的車次資訊。

2. 選擇一個車次,檢視對應的一等座、二等座等座位的餘票資訊。

3. 選擇一個有餘票的座位類型,随機配置設定座位,選擇一個或多個座位。然後選擇對應的使用者資訊,完成購票訂單操作。

4. 在規定時間内,在支付訂單界面,選擇一個訂單,選擇付款或者退票,完成最後的流程。

5. 遇到特殊情況,在已支付訂單界面,選擇一個訂單,選擇退票或者改簽操作。

窺一斑而知全豹,這一個購票流程已經給了我們大緻的系統面貌了,那麼得出大概的功能設計圖:

購票系統設計之餘票處理标題購票系統設計之餘票處理

三、分析系統

讓我們在腦海中模拟一下實際的開發過程,先開發背景管理系統。使用者、菜單、權限等子產品暫時先跳過,畢竟這不是本次思維風暴的重點。站點、列車、車次、座位,嗯,這幾個功能子產品看上去都是一些簡單維護操作,問題不大可以實作。

那就開始模拟使用者操作:

第一步根據站點和時間範圍選擇合适的車次資訊,沒問題,接着走。

第二步,檢視車次的餘票情況,咦,查不出來。看來我得加一張使用者的購票記錄表,記錄一下購票情況,才能座位數-已購票數=餘票。嗯?我隻有開始站點和結束站點的資訊,車次會經過N個站點,又不是隻有2個站點。要是這樣:A站點->B站點 ->C站點 -> D站點->E站點,有人中途買了C->D的座位Z1,那現在要購票從A->D的座位,那應該顯示沒有餘票了。不對,好像有點東西,完了,把自己繞進去了…

Two thousand years later…

唔,一個站點有票,一個站點沒有票,那不就是0和1嗎? ABCDE不就代表00000,如果有人買了C->D,那不就是00110,如果又有人買了D->E,那不就是00111。根據二進制的進位原理,C->D,占據了倒數第一位和倒數第三位的位置,對應的最小值應該是00001=1=21-1,最大值應該是00111=7=23-1,再結合實際推敲一下,值域應該是[23-1,21-1),下次買票肯定必須不能在這個區間買了,隻能是選擇兩端(+oo,23-1)U[21,-oo)。

那在車次表裡,在加一個經過站點屬性,再加一個座位購票記錄表,記錄每個座位的購票記錄,裡面有三個關鍵屬性,A屬性用來記錄二進制座位情況00000,B屬性用來記錄目前二進制的最小值(下次買票結束站點轉換的二進制值必須小于等于它),C屬性用來記錄目前二進制的最大值(下次買票的開始站點轉換的二進制值必須大于它)。

先查出對應的車次,在根據經過站點,确定兩個站點對應的二進制值V1,判斷V1是否大于C屬性值,V1是否小于等于B屬性就可以了。這裡使用sql條件查詢出對應的座位出來,同一座位的記錄數相加等于該座位的餘票數。

第三步,選擇座位購買,下訂單。這一步對應的就是,根據座位id去重新整理座位購票記錄表的ABC,把A屬性對應的0變為1。如果退票,那就是把對應座位的1改為0。

第四步,在半小時内付款,這裡累了,沒什麼好說的了。