Search code examples
c#sqlmathpolynomial-mathlogarithm

Logarithmic distribution of profits among game winners


I have a gave, which, when it's finished, has a table of players and their scores. On the other hand i have a virtual pot of money that i want to distribute among these winners. I'm looking for a SQL query or piece of C# code to do so.

The descending sorted table looks like this:

UserId | Name | Score | Position | % of winnings | abs. winnings $
00579  | John | 754   | 1        |  ?            | 500 $    
98983  | Sam  | 733   | 2        |  ?            | ?    
29837  | Rick | 654   | 3        |  ?            | ?    <- there are 2 3rd places
21123  | Hank | 654   | 3        |  ?            | ?    <- there are 2 3rd places
99821  | Buck | 521   | 5        |  ?            | ?    <- there is no 4th, because of the 2 3rd places
92831  | Joe  | 439   | 6        |  ?            | ?    <- there are 2 6rd places 
99281  | Jack | 439   | 6        |  ?            | ?    <- there are 2 6rd places 
12345  | Hal  | 412   | 8        |  ?            | ?    
98112  | Mick | 381   | 9        |  ?            | ?    
and so on, until position 50 
98484  | Sue  | 142   | 50       |  ?            | 5 $ 

Be aware of the double 3rd and 6th places.

Now i want to distribute the total amount of (virtual) money ($ 10,000) among the first 50 positions. (It would be nice if the positions to distribute among (which is now 50) can be a variable).

The max and min amount (for nr 1 and nr 50) are fixed at 500 and 5.

Does anyone have a good idea for a SQL query or piece of C# code to fill the columns with % of winnings and absolute winnings $ correctly?

I prefer to have a distribution that looks a bit logarithmic like this: (which makes that the higher positions get relatively more than the lower ones).

.
|.
| .
|  .
|   .
|     .
|        .
|            .
|                  .
|                           .

Solution

  • I haven't done SQL since 1994, but I like C# :-). The following might suit, adjust parameters of DistributeWinPot.DistributeWinPot(...) as required:

    private class DistributeWinPot {
    
        private static double[] GetWinAmounts(int[] psns, double TotWinAmounts, double HighWeight, double LowWeight) {
            double[] retval = new double[psns.Length];
            double fac = -Math.Log(HighWeight / LowWeight) / (psns.Length - 1), sum = 0;
            for (int i = 0; i < psns.Length; i++) {
                sum += retval[i] = (i == 0 || psns[i] > psns[i - 1] ? HighWeight * Math.Exp(fac * (i - 1)) : retval[i - 1]);
            }
            double scaling = TotWinAmounts / sum;
            for (int i = 0; i < psns.Length; i++) {
                retval[i] *= scaling;
            }
            return retval;
        }
    
        public static void main(string[] args) {
            // set up dummy data, positions in an int array
            int[] psns = new int[50];
            for (int i = 0; i < psns.Length; i++) {
                psns[i] = i+1;
            }
            psns[3] = 3;
            psns[6] = 6;
            double[] WinAmounts = GetWinAmounts(psns, 10000, 500, 5);
            for (int i = 0; i < psns.Length; i++) {
                System.Diagnostics.Trace.WriteLine((i + 1) + "," + psns[i] + "," + string.Format("{0:F2}", WinAmounts[i]));
            }
        }
    }
    

    Output from that code was:

    1,1,894.70
    2,2,814.44
    3,3,741.38
    4,3,741.38
    5,5,614.34
    6,6,559.24
    7,6,559.24
    8,8,463.41
    9,9,421.84
    10,10,384.00
    11,11,349.55
    12,12,318.20
    13,13,289.65
    14,14,263.67
    15,15,240.02
    16,16,218.49
    17,17,198.89
    18,18,181.05
    19,19,164.81
    20,20,150.03
    21,21,136.57
    22,22,124.32
    23,23,113.17
    24,24,103.02
    25,25,93.77
    26,26,85.36
    27,27,77.71
    28,28,70.74
    29,29,64.39
    30,30,58.61
    31,31,53.36
    32,32,48.57
    33,33,44.21
    34,34,40.25
    35,35,36.64
    36,36,33.35
    37,37,30.36
    38,38,27.64
    39,39,25.16
    40,40,22.90
    41,41,20.85
    42,42,18.98
    43,43,17.27
    44,44,15.72
    45,45,14.31
    46,46,13.03
    47,47,11.86
    48,48,10.80
    49,49,9.83
    50,50,8.95