Advertisement
Guest User

Untitled

a guest
Nov 22nd, 2019
123
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. class TrafficSplit{
  2.    
  3.     constructor(spec, volume){
  4.        
  5.         this.seed = (spec) => {
  6.             let results = {};
  7.             for(let i in spec) results[Object.keys(spec)[i]] = 0;
  8.             return results;
  9.         }
  10.        
  11.         this.weights = spec;
  12.         this.results = this.seed(spec);
  13.         this.volume = volume || 100;
  14.         this.retries = 0;
  15.        
  16.     }
  17.    
  18.     weightedRand = () => {
  19.         let i, j, table = [];
  20.  
  21.         // Fills up the table with the item (weight * 10) times
  22.         for (i in this.weights) {
  23.             // The constant 10 below should be computed based on the
  24.             // weights in the spec for a correct and optimal table size.
  25.             // E.g. the spec {0:0.999, 1:0.001} will break this impl.
  26.             for (j = 0; j < this.weights[i] * 10; j++) {
  27.                 table.push(i);
  28.             }
  29.         }
  30.  
  31.         // Pick a random value from the generated table
  32.         return table[Math.floor(Math.random() * table.length)];
  33.     }
  34.    
  35.     views = () => {
  36.         let views = 0;
  37.        
  38.         for(let i in Object.keys(this.results)){
  39.             views += this.results[Object.keys(this.results)[i]];
  40.         }
  41.        
  42.         return views;
  43.     }
  44.    
  45.     forceFloat = (num, points = 2) => {
  46.         return parseFloat(parseFloat(Math.round(num * 100) / 100).toFixed(points));
  47.     }
  48.  
  49.     decide = () => {
  50.         let _rand = this.weightedRand();
  51.         let _totalViews = this.views();
  52.         let _expectedWeight = this.forceFloat(this.weights[_rand]);
  53.         let _actualWeight = Math.abs(parseFloat((this.results[_rand] / _totalViews).toFixed(2)));
  54.        
  55.         console.log('Total Views:', _totalViews);
  56.         console.log('Random Chosen:', _rand);
  57.         console.log('Views of Random Chosen:', this.results[_rand])
  58.         console.log('Expected Weight:', _expectedWeight);
  59.         console.log('Actual Weight:', _actualWeight);
  60.        
  61.         if(_actualWeight > _expectedWeight && _actualWeight !== NaN){
  62.             console.log('Running over, calling again...\n\n');
  63.             this.retries++;
  64.             this.decide();
  65.         }
  66.         else{
  67.             console.log('');
  68.             this.results[_rand]++;
  69.             return _rand;
  70.         }
  71.     }
  72.    
  73.     test = () => {
  74.         let _totalViews;
  75.         let output = [];
  76.  
  77.         // Run the program <volume> times
  78.         for(let i = 0; i < this.volume; i++) this.decide();
  79.        
  80.         _totalViews = this.views();
  81.         for(let i in this.results){
  82.             let key = Object.keys(this.results)[i];
  83.             let views = this.results[i];
  84.             let percentage = views/_totalViews;
  85.             let efficiency = (_totalViews - this.retries) / this.volume;
  86.            
  87.             output.push({
  88.                 'Option': key,
  89.                 'Views': views,
  90.                 'Actual %': percentage * 100,
  91.                 'Expected %': this.weights[key] * 100,
  92.                 'Retries': this.retries,
  93.                 'Efficiency': Math.abs(efficiency)
  94.             })
  95.         }
  96.  
  97.         console.table(output);
  98.     }
  99. }
  100.  
  101. let split = {0: 0.20, 1: 0.20, 2: 0.20, 3: 0.20, 4: 0.10, 5: 0.10};
  102. new TrafficSplit(split).test()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement