Jump to content

Good algorithm?


subnet_rx

Recommended Posts

I'm trying to do some stats for a script I wrote, and now need to rank based on wins and losses.  Of course, wins must be more than losses, but I'd also like to take into consideration the amount of wins + losses so that someone that is 20-0 doesn't beat someone that is 100-25.  They probably should, however, beat someone that is 30-20.  I'm sure this has been tackled before, so does anyone know of a good source for algorithms like this? 

Link to comment
Share on other sites

Admin please move this to the math section

 

that being said you want to create a qualitative analysis.  I think what you need to think of is somehow a +/- system that is a progression, creating a point scale.

(this is very linear and could be rewritten to a equation)

For example

if you win a game and you have <10 wins it is +5 points, and a loss is -3 points

Then in the 10-20 games a win is only +4 and a loss is -2

 

Then you could apply a modifier, for example the exp gained/loss could be based off that base number * your wining percentage (so if i'm 3-2 (600% win) and I win a game I gain 5*.6 exp or a lost would be -3*.6)  that would keep people who lose a lot from sucking too bad, that or somehow do it based off the difference of wining from 500.

 

Just some ideas i'm throwing out

Link to comment
Share on other sites

yeah, sorry, didn't see the math section.  I was thinking about a point system too though.  I wasn't thinking as deeply as you describe though.  I was going to assign points for wins, points for your win/loss total, and points for your win/loss ratio.  I just wasn't sure if this is how people do this or if there's something that's standard that is way more complex. 

Link to comment
Share on other sites

I'd just go with losses / wins, and the lower the better.

 

If they have 0 wins, then sort them based on how many losses (more = bad).

 

And 20-0 should probably beat 100-25. 20-0 is winning %100 of the time, sure the sample size is smaller, but I bet once they get to a 100 they'll still have less than 25 losses.

Link to comment
Share on other sites

What are your range of tolerances on stuff. Like how many games is a normal percent (someone ranked in the 50% area play) and what is a godly range(someone in the top 2%) how many users do you have etc etc.

 

Everyone is at 0-0 right now.  There will be about 30-40 chances to win a week based on their guesses. 

Link to comment
Share on other sites

And how long is a ladder season.  Looking for a total possible games played and an average number of games played.  You could look into a differential equation that modifies its self based on total games played avg win/loss ratio avg games play and so forth.

 

Basically, it's a pick'em game that is focused on football right now.  High School, College, and NFL.  But, I will expand it to other sports as well.  If I had to guess, I'd say 150 games total in each.  And I am dividing them up.  I just do not want to do it simply based on record alone.  With these games, I could pick the ones everyone knows will win and ignore the others, and come out on top.  With a simple loss/win ranking, I could be 5-0 and be on top.  Where could I look into a differential equation that does modify itself based on the factors you list?

Link to comment
Share on other sites

Some how you have to develop something like

y = aW - bL +c where y>0 and it is a non linear function.  W = wins and L = losses. 

 

Since y>0 I think that subtracting bL might not be the smartest idea, but instead there be some ratio of W/G and L/G where G is total games played.  possibly a function in the nature of

 

y = a e^(W/g - L/g)) +b 

 

Where a changes with respect to g and b is a constant based on some factors you determine from experimental data (It can change from ladder to ladder)  This method will generate values always greater than 0 because a and b will be greater than 0.  However I think yet another modification must be applied in the power of e section such as multiplying it be w/2g or some sort in the power to give the nubmer of games a bigger meaning

 

Make up that equation as a function then test it for a bunch of number and play around but i think an expodential like this might be the best idea.  I'll try and come up with a quick tester in a minuite.

Link to comment
Share on other sites

I played around with a few things and came up with this that works pretty well, just need to take into account some sort of bonus for total games played, this code in here isn't 100% up to date as i'm playing with stuff as I find fit.  Notice that I made A=200 that creates significant figures with the final result since the final result is rounded (post being multiplied by A)

http://pira00.worldispnetwork.com/algo.php

<form method="get" action="<?php echo $_SERVER['self'];?>">
Number of Trails: <input type="text" name="trials" /><br/>
Number of Games: <input type="text" name="games" /><br/>
<input type="submit" />
</form>

<?php
if(!empty($_GET)){
$trails = $_GET['trials'];
$games = $_GET['games'];
$a = 200;
$b = 0;
$i = 0;
$j = 0;
while($i <= $trails){
	$j = 1;
	$win = 0;
	$loss = 0;
	while($j <= $games){
		$j++;
		$temp_game = rand(0,5);
		if($temp_game < 4){
			$win++;
		}
		else{
			$loss++;
		}
		//$pow = (($win/2*$j)*(($win/$j)-$loss/$j));
		$pow = ($win/($loss+1))*($win-$loss)/$j;
		$a2 = (.25*$j)+1; // So its always greater than 1
		$value = ceil(($a*$a2*exp($pow))+$b);
		echo "<br/>".$j." Games Played  Wins: ".$win." Loss: ".$loss." Values: ".$value;

	}
echo "<br/><br/>";
$i++;
}
}
?>

 

I think this is the best version right now as it reward players for lots of games, but if you don't have a good record you are done for.  I am also changing the rand win/loss to 1:1 instead of the 4:2 it is at now.  Run some and give me some feedback on it.

Link to comment
Share on other sites

B is something as a result of trial and error.  its there so if you want one season to compare to another quantitatively it will result in the same numbers based on a translation of -b.  Only issue I have seen with this is that the $a2 i introduced creates a bit of linearization that isn't needed.  It needs to be there, but maybe it needs some modifications to it to change it from a linearization to something else.  That or a2 needs to be applied outside of the general term.  This is where B comes into play i'll make a mod and run some test on it that way because I think it will do what we are seeking.  So lets say you have played 100 games you get a bonus of 25 pts vs playing 25 games u get a bonus of 6.25.

Link to comment
Share on other sites

I'll wait and see what you come up with.  Right now, I've plugged all the values in and am getting output for all 3 groups (high school, college, nfl), but even though I initialize everything at 0, the points add up to something different in each group.  In High School, a person with 0-0 gets 1500 points.  In college, which runs second, they get 4650.  By the time it gets to NFL, they have 7750.

 

Here's the relevant part of the code:

 

while ($users= $db->fetch_array($user_results))
{
	$wins[$users['userid']] = 0;
	$losses[$users['userid']] = 0;
	$points[$users['userid']] = 0;
	$totals[$users['userid']] = 0;
	$picks_results = $db->query_read("SELECT picks_bets_placed.userid,picks_bets_placed.outcome,picks_bets_placed.settled,picks_bets_placed.group_id,picks_groups.type FROM picks_bets_placed,picks_groups WHERE userid = ".$users['userid']." AND picks_groups.group_id = picks_bets_placed.group_id");
	while ($picks= $db->fetch_array($picks_results))
	{
		if($picks['outcome']=='W' AND $picks['type']==$type AND $picks['settled']=='Y')
		{
			$wins[$users['userid']] += 1;
		}
		elseif($picks['outcome']=='L' AND $picks['type']==$type AND $picks['settled']=='Y')
		{
			$losses[$users['userid']] += 1;
		}
	}
	$totals[$users['userid']] = $wins[$users['userid']] + $losses[$users['userid']];
	$win = $wins[$users['userid']];
	$loss = $losses[$users['userid']];
	//$pow = (($win/2*$j)*(($win/$j)-$loss/$j));
	$pow = ($win/($loss+1))*($win-$loss)/$outcomes;
	$a2 = (.25*$outcomes)+1; // So its always greater than 1
	$value = ceil(($a*$a2*exp($pow))+$b);
	$points[$users['userid']] = $value;
}

Link to comment
Share on other sites

I think we are thinking about this wrong.  Some how we need to give a win/loss some sort of weighting as i had based on total number of games played

 

Like if you have played 50 games a win is worth 1 and a loss is worth .5 but if u have 100 games then a win is worth .85 and a loss is .45 or some sort.  then we figure out that sum.  An equation for that is like

<?php
$factor_w = 100;
$factor_l = 85;
$games = 50;
$wins = 25;
$losses = 25;
$total = ($wins/($factor_w/$games))-($losses/($factor_l/$games));
?>

 

So this generates a value that will be put in to $a*exp($k*$total);  Where $k is to keep the values realistic and $a is to create more significance to the outputted value.  However this results in an issue because $total could be <0 which means if you have more losses than wins you are going to be really low down.  Somehow it has to be exponential, but somehow it has to take into account games and wins vs loss ratio.  we could just use that outputted $wins/$games which si your wining percentage.  then take exp($wins/$games)  which takes into account losses.  You seem to be worried about combining all three leagues together, but that isn't nessecary until after you get the inital values create.  Then its easy.  but the problem at hand is creating an equation where 25-0 is equal to 75-4 but less than 101-7 for example.

Link to comment
Share on other sites

Ohh, no, I want to have separate rankings for each type.  There are 3 now, but there could be 10 in the future.  So, I would like rankings for each.  That's why when I run this function, I run it dependent on a type variable.  The way I store the data now, I can know two totals.  The total number of outcomes since the league (type) started and the total number of wins/losses for the player.  What I do not know is the total number of outcomes since the player started.  I'm not recording time right now, but I intend to institute that very soon.

Link to comment
Share on other sites

Here's the complete function at this point:

 

function update_stats($type) 
{
    global $db;
    $a = 200;
    $points = array();
    $wins = array();
    $losses = array();
    $totals = array();
    $outcomes = $db->query_read("SELECT SUM(outcomes) FROM picks_groups WHERE type = ".$type."");
    $user_results = $db->query_read("SELECT * FROM picks_users");
    while ($users= $db->fetch_array($user_results))
    {
        $wins[$users['userid']] = 0;
        $losses[$users['userid']] = 0;
        $points[$users['userid']] = 0;
        $totals[$users['userid']] = 0;
        $picks_results = $db->query_read("SELECT picks_bets_placed.userid,picks_bets_placed.outcome,picks_bets_placed.settled,picks_bets_placed.group_id,picks_groups.type FROM picks_bets_placed,picks_groups WHERE userid = ".$users['userid']." AND picks_groups.group_id = picks_bets_placed.group_id");
        while ($picks= $db->fetch_array($picks_results))
        {
            if($picks['outcome']=='W' AND $picks['type']==$type AND $picks['settled']=='Y')
            {
                $wins[$users['userid']] += 1;
            }
            elseif($picks['outcome']=='L' AND $picks['type']==$type AND $picks['settled']=='Y')
            {
                $losses[$users['userid']] += 1;
            }
        }
        $totals[$users['userid']] = $wins[$users['userid']] + $losses[$users['userid']];
        $win = $wins[$users['userid']];
        $loss = $losses[$users['userid']];
        //$pow = (($win/2*$j)*(($win/$j)-$loss/$j));
        $pow = ($win/($loss+1))*($win-$loss)/$outcomes;
        $a2 = (.25*$outcomes)+1; // So its always greater than 1
        $value = ceil(($a*$a2*exp($pow))+$b);
        $points[$users['userid']] = $value;
    }
    arsort($points);
    foreach ($points as $key => $val) 
    {
        $id_results = $db->query_read("SELECT username FROM user WHERE userid = ".$key."");
        $id = $db->fetch_array($id_results);
        $username=$id['username'];
        $line_item .= "<tr><td>".$username."</td><td>".$wins[$key]."</td><td>".$losses[$key]."</td><td>".$points[$key]."</td></tr>";
        
    }
    return $line_item;
} 

Link to comment
Share on other sites

You might be interested in the ELO rating system.  It's used in chess and also in some online game rankings.

 

The basic idea is that when you play a match, your ranking changes depending on the result of the game and the ranking of your opponent.  People who win games against strong players will get high rankings, but people who win the same number of games against weaker players will still get low rankings.

 

You can calculate this in retrospect if you have a full history of games played.

 

For your situation, the rankings of your 100/25, 20/0 and 30/20 players would depend more on who they played than the win/loss ratios, which on their own can be quite misleading.  A 30/20 score against the top players should be ranked higher than a 20/0 score against the weakest ones.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.