Javascript mocks train ticket booking and refund examples

  • 2020-03-30 02:42:43
  • OfStack

I saw someone analyze the logic behind 12306 before. Booking and canceling train tickets is different from ordinary shopping.
One difficulty is that train tickets can be sold at different stations. For example, a train ticket from Beijing to Shanghai can have many stops along the way, can Beijing - jinan, jinan - nanjing... And so on. How to design the data model to access these tickets is a problem. It's not just the quantity plus minus 1.

For example, if there are 10 stops between Beijing and Shanghai, the initial status of a full ticket will be: '1111111111'.
When a full ticket is sold, the ticket becomes '0000000000';
A half ticket, such as beijing-jinan three stops (the first - the third), becomes' 0011111111 ';
Another half ticket is sold, such as xuzhou - nanjing (stops 6-9), and the previous ticket becomes: '0011100011';

The logic of unbooking a ticket is very simple, I want to return a ticket (xuzhou - nanjing), then from the ticket pool to find the first one can not buy
(xuzhou-nanjing) ticket, change it OK. For example, find the above ticket '0011100011',
After refund, the ticket becomes (0011111111);

As shown in the basic logic, to ensure multiple entries in 12306, and the consistency of data, it needs very efficient logic to handle ticket checking.
The ticket-buying, ticket-refunding business is said to have 200, 000 requests per second at its peak. Saves the ticket's data structure in memory. Not a database.
Small and efficient data knots become important.


if(jQuery){}else{
 //document.write
}
function Server(){
 var self = this;
 self.ticketsPool = [];
 self._init= function(number){
  if(typeof(number) != 'number')
   throw ('type error');
  for(i=0;i<number;i++){
   self.ticketsPool.push(new Ticket());
  }
 };
 //To determine whether or not a ticket can be bought, by an or.
 //For example, if order o is beijing-jinan (001111111), or a ticket is (0000000011) (sold beijing-nanjing), false is returned
 //For example: order o for Beijing - jinan (001111111), a ticket for (1111100011) (xuzhou - nanjing), return true
 self.canBuy = function(o,t){
  var _o = ''
  for(j=0; j<o.length; j++){
   _o += o[j]=='0'?1:0;
  }
  var r1 = (parseInt(t.tic,2) | parseInt(o,2)) & parseInt(_o,2);
  var r2 = parseInt(_o,2);
  return r1 == r2;
 };
 //Sell a ticket
 self.pop1Ticket = function(o){
   for(i=0;i < self.ticketsPool.length;i++){
    if(self.canBuy(o,self.ticketsPool[i])){
     self.buy(self.ticketsPool[i],o);
     return i;
   }
  };
  return -1;
 };
 //The implementation of selling tickets by changing binary strings, such as '111111111'-> '001111111'.
 self.buy = function(t,o){
  t.tic = (parseInt(t.tic,2) & parseInt(o,2)).toString(2);
  //alert(t.tic);
 };
 //Query more tickets
 self.remainTics = function(o){
   var count=0;
   for(i=0;i < self.ticketsPool.length;i++){
    count += self.canBuy(o,self.ticketsPool[i])?1:0;
  };
  return count;
 }
 //Refund, or calculation
 self.refund = function(o){
   for(i=0;i < self.ticketsPool.length;i++){
    if(!self.canBuy(o,self.ticketsPool[i])){
     var _o = ''
     for(j=0; j<o.length; j++){
      _o += o[j]=='0'?1:0;
     }
     self.ticketsPool[i].tic = (parseInt(self.ticketsPool[i].tic,2) | parseInt(_o,2)).toString(2);
     return i;
   } 
  };
  return -1;
 }
}
//Data model: tickets
function Ticket(){
 var self = this;
 //Tickets are initially full ticket
 self.tic = '1111111111';
}
//Data model: order
function Order(from, to){
 var self = this;
 var s = '';
 for(i=0;i<10;i++){
  s += (i>=from && i<to)?0:1;
 }
 return s;
}
//12306 the background
Server = new Server();
//At the beginning, there were 400 tickets in the ticket pool
Server._init(400);


Related articles: