zoukankan      html  css  js  c++  java
  • 初探12306售票算法

    1.以G71列车为例,首先对车次站台进行占位编码(从1开始到最后一站递加)

           

       对以上占位简单描述以下:G71总共18个站点那么我们的单个座位的座位标识可以用十八位长度的二进制字符串表示10000000000000000每一位代表一个站点,每天放票前初始化到下面的订票表中,数据如下余票根据座位标识中的0的个数决定最大余票数量

     订票表中的始发受限站点和终到受限站点可以灵活搭配(这个就可以实现限制站点发售)

     限售渠道十进制 7 代表 1(车站)| 2(互联网)|4(电话)=7 即该票允许  车站, 互联网, 电话同时出售

        那么还可以是 1|4 = 5  即该票只接受在车站和电话预定

       扩展 8(代售点) 16 (手机端) 

    2.查询余票

    如果我们要用互联网渠道查询日期为2016-06-11,始发站保定东站(3)到韶关站(15)的G71二等座F座位余票情况只需要执行如下sql(该SQL可以实现选座位和选车厢等功能)

    复制代码
    select GUID,车次编码,车次类型,座位类型,车厢号码,座位编码,座位位置,车票版本号 from 订票表
    
    where  to_number(substring(座位标识,3,15))=0
    
    and 发车日期='2016-06-11'
    
    and 车次编码='G71'
    
    and substring(始发受限车站,3,4)=1
    
    and substring(终到受限车站,15,16)=1
    
    and 车票状态='待售'
    
    and 车次类型='二等座'
    
    and 座位位置='F'
    and 受限渠道=2|受限渠道
    order by 余票数量 asc ,车厢 asc --先卖余票少的,防止打乱更多的长途票
    复制代码

    3.预定票

      3.1根据第二步中查询条件获取一条记录然后将车票状态改为锁定

      3.2待锁定成功后进行支付

         

    update 订票表 set 座位标识=座位标识 | 000111111111111000,车票版本号=车票版本号+1,余票数量 = 余票数量-(15-3)
          where GUID = Md5(车次+座位编码+发车日期) and 车票版本号=取得的版本号 --乐观锁
    
            根据更新结果是否为1则可以判定购票成功

      3.2支付成功后然后将保定到韶关的票保存到另外一张客户的车票表中

      3.3如果指定时间没有支付,那么直接调用退票sql

    4.退票

      获得该车次保定到韶关的票 (000111111111111000)与对应的票进行非运算,则即可回归票池子了

    5.选座

           

    复制代码
    update 订票表 set 座位标识=座位标识 ^ 000111111111111000,余票数量 = 余票数量+(15-3),车票版本号=车票版本号+1
    
         where GUID = Md5(车次+座位编码+发车日期)  and 车票版本号=取得的版本号 --乐观锁
    根据返回结果为1则标识退票成功
    复制代码

    以下为相关java代码 

    复制代码
      1 import java.math.BigDecimal;
      2 
      3 public class MainTest {
      4     public static void main(String[] args) {
      5         String ticketFlag = "100000000000000000";
      6         int beginStation = 3;
      7         int endStation = 15;
      8         long beginTime = System.currentTimeMillis();
      9         String result = orderTicket(ticketFlag, beginStation, endStation);
     10         if (result.equals(ticketFlag)) {
     11             System.out.println("订票失败");
     12         } else {
     13             System.out.println("订票后的结果:" + result);
     14             // 如果要取消的话,就进行这个操作
     15             String b = buildTicket(ticketFlag.length(), beginStation,
     16                     endStation);
     17             System.out.println("释放后的结果:" + releaseTicket(ticketFlag, b));
     18 
     19         }
     20         long endTime = System.currentTimeMillis();
     21         System.out.println("耗时:" + (endTime - beginTime));
     22     }
     23 
     24     /**
     25      * 订票
     26      * 
     27      * @param ticketFlag
     28      * @param beginStation
     29      * @param endStation
     30      * @return
     31      */
     32     private static String orderTicket(String ticketFlag, int beginStation,
     33             int endStation) {
     34         String result = "";
     35         if (checkCanTicket(ticketFlag, beginStation, endStation)) {
     36             String b = buildTicket(ticketFlag.length(), beginStation,
     37                     endStation);
     38 
     39             String currentTicked = toTicket(ticketFlag, b);
     40             System.out.println("预占票前结果:" + ticketFlag);
     41             result = currentTicked;
     42         } else {
     43             result = ticketFlag;
     44         }
     45         ;
     46         return result;
     47     }
     48 
     49     /**
     50      * 取消已定票
     51      * 
     52      * @param ticketFlag
     53      * @param b
     54      * @return
     55      */
     56     private static String releaseTicket(String ticketFlag, String b) {
     57         StringBuilder tempSt = new StringBuilder("");
     58         int length = ticketFlag.length();
     59         for (int i = 0; i < length; i++) {
     60             char tempA = ticketFlag.charAt(i);
     61             char tempB = b.charAt(i);
     62             if (tempA == '1' && tempB == '1') {
     63                 tempSt.append("0");
     64             } else {
     65                 tempSt.append(tempA);
     66             }
     67         }
     68         return tempSt.toString();
     69     }
     70 
     71     /**
     72      * 创建区间占位票
     73      * 
     74      * @param length
     75      * @param beginStation
     76      * @param endStation
     77      * @return
     78      */
     79     private static String buildTicket(int length, int beginStation,
     80             int endStation) {
     81         StringBuilder st = new StringBuilder("");
     82         for (int i = 0; i < length; i++) {
     83             if (i >= beginStation && i < endStation) {
     84                 st.append("1");
     85             } else {
     86                 st.append("0");
     87             }
     88         }
     89         System.out.println("创建区间票:" + st.toString());
     90         return st.toString();
     91     }
     92 
     93     /**
     94      * 生成订票后的结果
     95      * 
     96      * @param ticketFlag
     97      * @param b
     98      * @return
     99      */
    100     private static String toTicket(String ticketFlag, String b) {
    101         StringBuilder tempSt = new StringBuilder("");
    102         int length = ticketFlag.length();
    103         for (int i = 0; i < length; i++) {
    104             char tempA = ticketFlag.charAt(i);
    105             char tempB = b.charAt(i);
    106             if (tempA == '1' || tempB == '1') {
    107                 tempSt.append("1");
    108             } else {
    109                 tempSt.append(tempA);
    110             }
    111         }
    112         return tempSt.toString();
    113     }
    114 
    115     /**
    116      * 是否可以订票
    117      * 
    118      * @param ticketFlag
    119      * @param beginStation
    120      * @param endStation
    121      * @return
    122      */
    123     private static boolean checkCanTicket(String ticketFlag, int beginStation,
    124             int endStation) {
    125         boolean result = false;
    126         String tempTicket = ticketFlag.substring(beginStation, endStation);
    127         BigDecimal b = new BigDecimal(tempTicket);
    128         if (b.equals(new BigDecimal("0"))) {
    129             result = true;
    130         }
    131         return result;
    132     }
    133 
    134 }
    复制代码

     

  • 相关阅读:
    react ts axios 配置跨域
    npm run eject“Remove untracked files, stash or commit any changes, and try again.”错误
    java 进程的参数和list的线程安全
    帆软报表 大屏列表跑马灯效果JS
    帆软报表 快速复用数据集,避免重复劳动
    分析云 OA中部门分级思路和实现方法
    分析云 分段器 只显示一个块的数据
    分析云 更改服务默认的端口号
    分析云U8项目配置方法新版本(2)
    Oracle 创建时间维度表并更新是否工作日字段
  • 原文地址:https://www.cnblogs.com/ywsoftware/p/5195731.html
Copyright © 2011-2022 走看看