Advertisement
Guest User

Untitled

a guest
Jan 27th, 2018
246
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
HTML 4.48 KB | None | 0 0
  1. <!doctype html>
  2.  
  3. <html>
  4.  
  5.   <head>
  6.     <meta charset="utf-8">
  7.     <meta name="viewport" content="width=device-width, initial-scale=1" />
  8.     <title>Flood Distribution</title>
  9.     <style>
  10.       html {
  11.         font-family: sans-serif;
  12.         font-size: 18px;
  13.       }
  14.      
  15.       body {
  16.         margin: 1rem;
  17.       }
  18.      
  19.       label[for] {
  20.         display: block;
  21.         font-weight: bold;
  22.       }
  23.      
  24.       input {
  25.         box-sizing: border-box;
  26.         font-size: 1rem;
  27.       }
  28.      
  29.       input + label {
  30.         margin-top: 1rem;
  31.       }
  32.      
  33.       input[readonly] {
  34.         border: 0;
  35.       }
  36.      
  37.       @media (max-width: 800px) {
  38.         html {
  39.           font-size: 26px;
  40.         }
  41.         input {
  42.           width: 100%;
  43.         }
  44.       }
  45.  
  46.     </style>
  47.   </head>
  48.  
  49.   <body>
  50.     <label for="fractions">Fractions:</label>
  51.     <input id="fractions" type="number" min="0" max="4" value="2">
  52.     <label for="budget">Budget:</label>
  53.     <input id="budget" type="number" value="100.00" step="0.01">
  54.     <label for="budget">Demanded:</label>
  55.     <input id="demanded" value="50, 20, 75, 10">
  56.     <label for="given">Given:</label>
  57.     <input id="given" readonly/>
  58.     <label for="given">Remaining Budget:</label>
  59.     <input id="remaining" type="number" readonly>
  60.     <script>
  61.       // @ts-check
  62.  
  63.       /**
  64.        * Distributes the budget by equally raising each party's share until their
  65.        * demand is met, the budget is spent, or the remaining amount can't be divided
  66.        * any further (e.g. $0.01).
  67.        * @param demanded {number[]}
  68.        * @param budget {number}
  69.        * @param fractions {number}
  70.        * @returns {[number[], number]}
  71.        */
  72.       function distribute(demanded, budget, fractions) {
  73.         let multiplier = 10 ** fractions;
  74.         // Ensure it's actually an int.
  75.         // E.g. 10.2 * 100 = 1019.9999999999999
  76.         let remaining = Math.round(budget * multiplier);
  77.         let data = demanded.map(
  78.           (value, index) => ({
  79.             demanded: value * multiplier,
  80.             index,
  81.             got: 0
  82.           })
  83.         );
  84.         // The demand is sorted in ascending order.
  85.         data.sort((a, b) => a.demanded - b.demanded);
  86.         for (let i = 0; i < data.length; i++) {
  87.          let left = data.length - i;
  88.          let demanded = data[i].demanded;
  89.          // Since everyone can get at least as much as the current party demands,
  90.          // this party gets what it asked for.
  91.          if (remaining > demanded * left) {
  92.             data[i].got = demanded;
  93.             remaining -= demanded;
  94.           }
  95.           // If it's less or exactly as much, distribute whatever remains among
  96.           // the remaining parties and quit.
  97.           else {
  98.             let share = Math.floor(remaining / left); // 10 / 3 -> 3
  99.             for (let k = i; k < data.length; k++) {
  100.              data[k].got = share;
  101.            }
  102.            remaining -= share * left; // 3 * 3 -> 9, 1 remains
  103.             break;
  104.           }
  105.         }
  106.         // Restore the original order.
  107.         data.sort((a, b) => a.index - b.index);
  108.         return [data.map(v => v.got / multiplier), remaining / multiplier];
  109.       }
  110.  
  111.       function main() {
  112.         let qs = document.querySelector.bind(document);
  113.         let $budget = qs('#budget');
  114.         let $demanded = qs('#demanded');
  115.         let $given = qs('#given');
  116.         let $remaining = qs('#remaining');
  117.         let $fractions = qs('#fractions');
  118.  
  119.         function format(v, f) {
  120.           return v.toFixed(Number.isInteger(v) ? 0 : f);
  121.         }
  122.  
  123.         function update() {
  124.           let demanded = $demanded.value.split(',').map(s => +s.trim());
  125.           let budget = +$budget.value;
  126.           let fractions = +$fractions.value;
  127.           let [given, remaining] = distribute(demanded, budget, fractions);
  128.           $given.value = given
  129.             .map(v => format(v, fractions))
  130.             .join(', ');
  131.           $remaining.value = format(remaining, fractions);
  132.         }
  133.  
  134.         $budget.addEventListener('input', update);
  135.         $demanded.addEventListener('input', update);
  136.         $fractions.addEventListener('input', () => {
  137.           let fractions = +$fractions.value;
  138.           $budget.value = (+$budget.value).toFixed(fractions);
  139.           $budget.step = 1 / (10 ** fractions);
  140.           update();
  141.         });
  142.  
  143.         update();
  144.       }
  145.  
  146.       document.addEventListener('DOMContentLoaded', main);
  147.  
  148.     </script>
  149.   </body>
  150.  
  151. </html>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement