Advertisement
apexsquirt

[PHP-CLI] "Gradual" Condorcet

Sep 5th, 2020 (edited)
303
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 7.09 KB | None | 0 0
  1. <?php
  2.  
  3. // download php on : https://www.php.net/downloads.php
  4.  
  5. // each vote will be stocked within a single .csv file.
  6. // for example, if you have a proposition "prop1", and vote :
  7.    // 24% on fuck no
  8.    // 30% on meh
  9.    // 47% on okay
  10.    // 50% on good
  11.    // 68% on pretty good
  12.    // 98% on hell yeah
  13. // then you'll have a line in "prop1.csv" where it's written :
  14.    // 24,30,47,50,68,98
  15.  
  16. // each vote will be stocked in arrays, which look like :
  17.    /* [24,30,47,50,68,98] */
  18. // with each being percentages for, from left-to-right :
  19.    // fuck no
  20.    // meh
  21.    // okay
  22.    // good
  23.    // pretty good
  24.    // hell yeah
  25.  
  26. function csv2arr ($path) {
  27. /* description */
  28.  // converts a csv file's content in a 2d array (table),
  29.  // csv files being big tables of data separated by commas.
  30. /* use */
  31.  // we'll stock votes from prop1.csv to propn.csv for n=2, or 3, ...
  32.  // we'll have to convert them into 2d arrays (tables) to use them.
  33. /* parameter(s) */
  34.  // $path
  35.     // path of the csv file.
  36.     // here it's just "1.csv", "2.csv", etc.
  37.     // that's bcs they're all in the same folder as this program.
  38.    
  39.     $file = file($path);
  40.     // file($path) creates an array with each line,
  41.     //  and $file = file($path); assigns the array of
  42.     //  file($path) to $file.
  43.     // however, right now it's still not very usable,
  44.     //  because it thinks these are just big strings
  45.     //  of characters with lots of commas in there.
  46.     // we therefore need to convert those strings
  47.     //  into arrays, which is what we'll do here :
  48.    
  49.     foreach ($file as $index => $eval) {
  50.     // foreach ($path as $index => $eval) runs through the $file array,
  51.     //  and at each step it assigns the index to $index and the string
  52.     //  content to $eval (which i called like that bcs they'll have to
  53.     //  be evaluated).
  54.         eval("\$ret[$index] = [$eval];");
  55.         // in those csv files, there are just numbers.
  56.         // in php, we can define an array $array of numbers as such :
  57.            /* $array = [24,30,47,50,68,98]; */
  58.         // eval() evaluates the expression within the input, and if,
  59.         //  for example, $eval = "24,30,47,50,68,98", then "[$eval]"
  60.         //  which will be evaluated as :
  61.            /* [24,30,47,50,68,98] */
  62.         // hence, "\$ret[$index] = [$eval];" will assign the evaluated
  63.         //  array eval("[$eval]") to $ret[$index]. in this example,
  64.         //  it will assign [24,30,47,50,68,98] to $ret[$index].
  65.     }
  66.    
  67.     return $ret;
  68.     // the resulting array of arrays / 2d array / table will be returned
  69.     //  by the function. so for example, if we have :
  70.        /* $ret[0] = [24,30,47,50,68,98] */
  71.     //  we can then reach the first value, 24, doing $ret[0][0], the
  72.     //  second with $ret[0][1], the third with $ret[0][2], etc.
  73.    
  74. }
  75.  
  76. $dir = scandir(".");
  77. // takes all the files in the folder and puts their name and extension in
  78. //  an array. if you put the csv files in a specific subfolder, replace "."
  79. //  by the name of said folder in quotation marks.
  80.  
  81. foreach ($dir as $fileNameExt) {
  82. // runs through each file, and assigns to $file the name and extension of
  83. //  each file in the folder at each step.
  84.  
  85.     if (strpos($fileNameExt,".csv") !== false) {
  86.     // if the file is a .csv file...
  87.        
  88.         $propositions[str_replace(".csv","",$fileNameExt)] = csv2arr($fileNameExt);
  89.         // each proposition voting tables/.csv files will be assigned their
  90.         //  .csv table converted into arrays, so we can actually use them.
  91.         //  the str_replace(".csv","",$fileNameExt) removes the extension to
  92.         //  $fileNameExt, which is basically just the file name then lol.
  93.        
  94.     }
  95.  
  96. }
  97.  
  98. function linear_interpolation ($array) {
  99. /* description */
  100.  // maps each percentage $array[0..5] to $ret[0], $ret[20], $ret[40],
  101.  //  $ret[60], $ret[80], $ret[100], and use linear interpolation to fill
  102.  //  in the gaps, and rounding all the values to the nearest integer.
  103.  // basically the v function which was presented in the video.
  104. /* use */
  105.  // we will use it along with condorcet's method to determine the condorcet
  106.  //  winning percentage which will be assigned to the proposition.
  107. /* parameter(s) */
  108.  // $array
  109.     // one of the arrays from $propositions[..] tables.
  110.    
  111.     foreach ($array as $score => $percentage) {
  112.     // runs through all the percentages and scores given.
  113.        
  114.         $ret[$score*20] = round($percentage);
  115.         // maps each percentage $array[0..5] to $ret[0], $ret[20], $ret[40],
  116.         //  $ret[60], $ret[80], $ret[100].
  117.        
  118.         if ($score < 5)
  119.             for ($i = $score*20+1; $i < ($score+1)*20; $i++)
  120.                 $ret[$i] = round(($array[$score+1]-$percentage)
  121.                                   * ($i-$score*20)/20
  122.                                  + $percentage)+rand(-50,49)/100;
  123.         // that's the linear interpolation part, we fill the gaps for indices
  124.         //  other than 0, 20, 40, 60, 80 or 100, and rounds the values. the
  125.         //  rand(-50,49)/100 value added gives a random value betwen -0.5 and
  126.         //  +0.49 in order to randomly sort tying rounded values in (*).
  127.        
  128.     }
  129.    
  130.     return $ret;
  131.    
  132. }
  133.  
  134. // <minor function>
  135. function array_of_indices (&$array) {
  136.    
  137.     $ret = [];
  138.     foreach ($array as $index => $content)
  139.         $ret[count($ret)] = $index;
  140.     $array = $ret;
  141.    
  142.     // pretty self-explainatory
  143.    
  144. }
  145. // </minor function>
  146.  
  147. foreach ($propositions as $fileName => $votes) {
  148.    
  149.     $preferences[$fileName] = [];
  150.    
  151.     foreach ($votes as $index => $vote) {
  152.        
  153.         for ($i = 0; $i < max($vote); $i++) {
  154.         // we will count each vote as if it were as many votes as the maximum
  155.         //  percentage of all the ones given in the vote.
  156.            
  157.             $tmp = linear_interpolation($vote);
  158.             // we stock the array of this linearly interpolated vote temporarily.
  159.            
  160.             arsort($tmp); // (*)
  161.             array_of_indices($tmp);
  162.             $preferences[$fileName][count($preferences[$fileName])] = $tmp;
  163.            
  164.         }
  165.        
  166.     }
  167.    
  168. }
  169.  
  170. function maximal_lotteries ($votes) {
  171. /* description */
  172.  // we use condorcet's method first, aka we take each percentages on 1-to-1
  173.  //  contests with each other and make an array of all the
  174. /* use */
  175.  // we will use it along with condorcet's method to determine the condorcet
  176.  //  winning percentage which will be assigned to the proposition.
  177. /* parameter(s) */
  178.  // $votes
  179.     // self-explainatory.
  180.    
  181.     foreach ($votes as $vote) {
  182.    
  183.         for ($percentage1 = 0; $percentage1 <= 100; $percentage1 += 1) {
  184.                                                 //                  |
  185.                                                 // you can give higher
  186.                                                 // values to faster, but
  187.                                                 // you will lose accuracy
  188.                                                 //                  |
  189.         for ($percentage2 = 0; $percentage2 <= 100; $percentage2 += 1) {
  190.            
  191.             if ($percentage1 != $percentage2)
  192.             $ranking[$percentage1] += intval(array_search($percentage1,$vote)
  193.                                         <=   array_search($percentage2,$vote));
  194.            
  195.         }}
  196.        
  197.     }
  198.    
  199.     $condorcet = [];
  200.    
  201.     for ($percentage = 0; $percentage <= 100; $percentage++) {
  202.        
  203.         if (max($ranking) == $ranking[$percentage])
  204.             $condorcet[count($condorcet)] = $percentage;
  205.        
  206.     }
  207.    
  208.     return $condorcet[rand(0,count($condorcet)-1)];
  209.    
  210. }
  211.  
  212. print "\n  Results (can take a while) :\n";
  213.  
  214. foreach ($preferences as $proposition => $votes) {
  215.    
  216.     print "   - $proposition : ".maximal_lotteries($votes)." %\n";
  217.     // gives the final results
  218.    
  219. }
  220. print "\n  If there is a tie, you can :
  221.   - Run the program again
  222.   - Pick a random winner in the ones with the highest percentage\n";
  223.  
  224. system("pause>nul");
  225.  
  226. ?>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement