Combining ladders across multiple servers

General Stuff about Armagetron, That doesn't belong anywhere else...
User avatar
Lucifer
Project Developer
Posts: 8640
Joined: Sun Aug 15, 2004 3:32 pm
Location: Republic of Texas
Contact:

Combining ladders across multiple servers

Post by Lucifer »

Ok, it's not perfect, but it's an epiphany, what did you expect? ;)

Here's how it should be done. First, the assumptions. The ladder is like a single frame in a movie. As a snapshot, it's fairly worthless. It gains meaning only through it's evolution over time. It's intended to show every player's skill in relation to each other. Now, different servers have different skills that are emphasized, so someone at the top of the ladder on one server wouldn't necessarily be at the top on another, and so forth. The only way a ladder from one server makes sense to combine with the ladder on another server is if you do so relatively, rather than absolute.

So discard the points column, we don't need it.

Take the ranking, divide by the total number of players. Do this for each server. You'll wind up with a number in the interval (0,1]. We'll call this the rank score, different than the ladder score which we've discarded. Now take each player that plays on multiple servers and average his rank scores. Do not count servers he doesn't play on at all, period. So if he only plays on 3, but you're combining 5, add his 3 rank scores together and divide by 3. That's his combined rank score. Now sort combined rank scores in ascending order and you have your combined rankings.

In this manner, if you're top dog on a 20 player server, you're rank score is 1/20. If you're top dog on a 100 player server, that's a bigger accomplishment, your rank score is 1/100 (we sort in ASCENDING order, so the lowest rank score the better you are, relative to the other players).

The underlying assumption is that points are used to determine rank on a single server, but that's as far as they're useful. The relative positions of the players is the only piece of data that's useful for combining ladders, so that's what we use. The weakness can be seen by looking at Chills on the breakfast stat page. He has quite a lead over #2, and that should count for something on the larger ladder.

An option, though, is to total up the number of points earned by all players on all servers, then total each player's points for each server they play on and divide that by the grand total. Then sort in DESCENDING order to determine rank. (right? Descending order for this?)

That's how you combine individual frames from each server. Now we need to put each frame in a database and graph over time. :) (Good luck on this one, I say, but that's the only way the data becomes useful) Now we can see who's normally at the top, and we can even adjust for spikes and possibly make a single aggregated ladder. So the old saying about "Anyone can show up, win 5 matches against sucky players, and be at the top of the ladder" gets its adjustment when you've collected the information over time.

Comments? This a big enough project for you, Tank? ;)

(Tank, you might want to move this to where you me and ish were talking about this sort of thing already, I wanted to get it down before I forgot so I ddin't dig up that thread. Up to you, we can talk about it here just as well :) )
Image

Be the devil's own, Lucifer's my name.
- Iron Maiden
User avatar
Z-Man
God & Project Admin
Posts: 11587
Joined: Sun Jan 23, 2005 6:01 pm
Location: Cologne
Contact:

Post by Z-Man »

Sounds good.

But averaging over all servers you play on will give those who concentrate on just one server an advantage. And logging in just once into another server will let you drop massively because now suddenly this server's rank score will get included into the average, too.

Since it is intrinsically hard to compare players that concentrate on one server vs. players that play many servers, I'd suggest this: Make different global ladders. Each of these ladders will have a number N. When the rank scores get averaged, your N best ( lowest? ) rank scores will get averaged. If you are listed on less than N servers, either assume you got a score of 1 on the missing servers or deny listing in that ladder. Then the players can argue about which of these ladders is the "right" one :)

My physics education suggests another way of determining your global score: Fix a real positive number L. Store all your individual rank scores in an array s[], sorted so that your best score is in s[0]. Calculate the sum over all s * exp(i*L), divided by the sum over all exp(i*L) ( in both sums, i runs from 0 to the number of servers you play on minus one ). The exponential decay will make your not-so-good scores less and less important, the division will normalize your total score to (0,1]. Experiment with different values of L. L=0 would be Lucifers suggestion, L=1/N would be similar in effect to my first suggested modification.

Yet another way not to punish players who visit more servers would be to ALWAYS assume there is one additional server you play on where you get the worst possible score. This would hurt single-server-players more than multi-server-players.
User avatar
/dev/null
Shutout Match Winner
Posts: 819
Joined: Sat Sep 04, 2004 6:28 pm
Location: Chicago-ish

Post by /dev/null »

Also, since servers are ran by people, you could very easily fluff your score by editing the text file. For this to work we would need some kind of centrally handled server for the scores and some way to trust the servers reporting those scores.
ishAdmin
Match Winner
Posts: 625
Joined: Sun Jul 04, 2004 12:11 am
Contact:

Post by ishAdmin »

is there no trust left in the world dev? :) But I do like the idea of a central reporting location - more on that below.

I was going to say a more simple version of what z-man said, except I still would prefer one single rank number on one single global ladder.

The missing element in this equasion is the rounds or matches played. If I win 1 out of 10 matches I play, and someone else wins 5 out of 10 matches they play, well we know who deserves a higher rank. The same goes for rounds won against rounds played. If we don't have that info, then I guess we are left with using the ladder as discussed. The problem with the ladder scoring is that you only need survive the round. You don't have to kill at all, win a match or even a round and be number one on the ladder. I can go on almost any server and put myself in the top 10 (maybe better) on the ladder in less than an hour if good players are there (with good ladder position) and I simply avoid death.

So, I guess I'm saying that perhaps before a global ladder system is devised, there should be some fixing to how the ladder calculates.

Or, a way around the individual ladders. > If a true global stats server were set up (and I'd be happy to host it, as well as many others I'm sure), I would like to see AA report to it who played each round, who won the round, how many kills each player had, match wins, etc. Then the global ladder server itself could do all the calculations. It doesn't need to know the ladder on each server. It would have the raw play data to do it's own more advanced calculations.

And the reporting to the global ladder wouldn't need to be anything more than simply writing a properly formatted log file that the global ladder could read once a day and parse out the data. (I'd have the game rotate the log once a day, and the global server would grab the previous FULL day of info once a day). Anyway, there are lots of ways to pass the data, I'm suggesting we don't need to go the route of sockets etc. KISS.
Image
User avatar
Tank Program
Forum & Project Admin, PhD
Posts: 6711
Joined: Thu Dec 18, 2003 7:03 pm

Post by Tank Program »

I was just sorta gonna add things up and devide and do stuff and viola and yeah... As long as the math for it can be done in php... Yeah. I'll have a prototype stats system today or tomorrow. Then we can tweak the math. Or something.

As for that info you want ishAdmin on scores at the ends of rounds and matches... Have you looked at scorelog.txt recently?
Image
User avatar
Lucifer
Project Developer
Posts: 8640
Joined: Sun Aug 15, 2004 3:32 pm
Location: Republic of Texas
Contact:

Post by Lucifer »

I agree with what ish has implied but not exlpicitly said. :) We need to measure a person's abilities in many more ways than what's currently available, in fact, it could be said that what's currently available isn't even accurate enough to make a ladder.

Making a ladder is like ranking everyone by IQ--some players think they're Mensa and that it means something while others are just getting inaccurate measurements.

I think we need more ways to score, personally. If I could change the scoring system, here's what I'd do:

1. Change the condition required to win a round to "scores the most points during the round". So you could score 3 points right away and die and still win the round because nobody else could top it.

2. More ways to score points. Say a really tight grind should be worth a point. Sustained high speeds should be worth points. On the other hand, if it's clear you're trying to adjust to get a tighter grind, then dying while doing so should be worht a negative point. Killing someone who's traveling significantly faster than you and doing so within a certain radius from your cycle should be worth more points than if that faster guy killed you (assumption: it's harder to kill someone when you're going waaaaay slower and they attack you). On the other hand, if he just bumbles into your wall on account of bad aim that shouldn't be worth a point to anyone. Hrm.

Average distance from walls on both sides could be used to determine someone's mazing, and good, sustained mazing could earn points.

3. Track more stuff. Ish already hinted at this, to get really good statistics we need to know how many rounds were played. We should also know how many matches were played, beginning to end. Not sure about saving fractions of matches. It would be nice if we knew who played each round, or if the game could use existing stats to come up with a "danger level" or something for the round, so if you win a round against players at the top of the ladder you should theoretically be scored better than if you win against players farther down. So you couldn't just kill noobs to get to the top of the ladder.

Yeah, if I ran the zoo, I'd make a few changes that's just what I'd do.
Image

Be the devil's own, Lucifer's my name.
- Iron Maiden
User avatar
Z-Man
God & Project Admin
Posts: 11587
Joined: Sun Jan 23, 2005 6:01 pm
Location: Cologne
Contact:

Post by Z-Man »

ishAdmin wrote: Or, a way around the individual ladders. > If a true global stats server were set up (and I'd be happy to host it, as well as many others I'm sure), I would like to see AA report to it who played each round, who won the round, how many kills each player had, match wins, etc. Then the global ladder server itself could do all the calculations. It doesn't need to know the ladder on each server. It would have the raw play data to do it's own more advanced calculations.
Actually, there is already code for that in AA. It was designed for the krawall servers and would send the scoring information back to the master server.
Of course, this system could be abused as easily as the polling version. A server sending fake match results to the scoring server would be easy to set up. Although, of course, simply editing a text file would be easier. One way or the other, I think we can only use the results from selected servers for a global ranking. Any server with obvious abuse would be deleted from the list.

And about the ladder not reflecting the true skills of a player:
Absolutely. The ladder is from a time when Armagetron was unable to determine who killed whom, so it had to use the information that was available. Today, I would use a simple system of "A kills B of another team => B gives A some of his ladder score". But I'm not touching the ladder right now, it's in gGame.cpp :o
User avatar
Tank Program
Forum & Project Admin, PhD
Posts: 6711
Joined: Thu Dec 18, 2003 7:03 pm

Post by Tank Program »

Well, I've written the code to compile all the info into one array, ie, from multiple servers. I did it in PHP. Possibly a mistake. It's been running the last 15 minutes combing the stats from all the Tigers Network servers... And this is the test run...
Image
User avatar
Tank Program
Forum & Project Admin, PhD
Posts: 6711
Joined: Thu Dec 18, 2003 7:03 pm

Post by Tank Program »

I did another instance of it with a mini set of files, 5 ppl in 4 files, 1 server. It worked. However, the "test" is still running. 3 hours later. I need a better way to do this... Just a wee set back... New algorithim for mergeing the data is necessary...
Image
ishAdmin
Match Winner
Posts: 625
Joined: Sun Jul 04, 2004 12:11 am
Contact:

Post by ishAdmin »

There must be a boo boo in there tank, no way it should take that long. I've found php to be pretty fast actually. I've done some heavy voo doo in it and it always burped up quickly.
As for that info you want ishAdmin on scores at the ends of rounds and matches... Have you looked at scorelog.txt recently?
um, yes, I have. I was thinking of expanding on that, and having something a little more suitable for computer reading, unix style timestamps etc. And it could skip the final scores synopsis for example.

But I really like what luci said about winning rounds being based on kills in the round instead of surviving. Surviving would only be the tie breaker. Hmm, what about ties amongst people who are both dead? Anyway, lots of ways it could be updated.

And that makes me think of one more thing. Kills are often credited to the wrong person. (although that's never happened to me ;) If we make the ladder, scoring and global stats depend more on actual kill credits, should that part of the game code be looked at? I admit I'll sometimes grind someone's trail in case they kill themselves so I might get the point. (shame on me) In those cases, I don't really earn that point. I imagine it's quite a difficult task to give credit to the right place. Anyway, can't do it all at once right! Could leave that for a future project.
Image
User avatar
n54
MVP
Posts: 1587
Joined: Sun Dec 21, 2003 12:40 pm

Post by n54 »

how about keeping track of how many times each player has coredumped each other?

would be kinda massive but wouldn't how often one has managed to kill anyone else be the perfect ladder basis? not that it would say anything about who's best, just who overall manages to kill anybody else...

hmm did this idea get through? hard to describe in detail...

attempt at a simple example:

round x
a kills b, c and f
b, e & f kills noone
c kills d
d kills e and g
g kills a (i.e. all dies during this round)

ladder result after round x
a
d
c & g (shared)
b, e & f (shared)

as more and more rounds are added it gets more and more precise but this simple example needs an advanced way of comparing the value of who/how many times killed between players, i.e. if there is one player many have killed those kills count less etc.

i said it would be massive lol it's just a though maybe not a good one :)
User avatar
Lucifer
Project Developer
Posts: 8640
Joined: Sun Aug 15, 2004 3:32 pm
Location: Republic of Texas
Contact:

Post by Lucifer »

Tank Program wrote:I did another instance of it with a mini set of files, 5 ppl in 4 files, 1 server. It worked. However, the "test" is still running. 3 hours later. I need a better way to do this... Just a wee set back... New algorithim for mergeing the data is necessary...
How are you merging it? If you want, you can throw your code up and I can see if I can help you speed it up...
Image

Be the devil's own, Lucifer's my name.
- Iron Maiden
User avatar
Tank Program
Forum & Project Admin, PhD
Posts: 6711
Joined: Thu Dec 18, 2003 7:03 pm

Post by Tank Program »

Right, here's the code that's STILL running :oops:...

Code: Select all

<?php

set_time_limit(0);

$servers = array(
  0 => "http://url/to/data/"
);

$types = array(
  0 => "highscores.txt",
  1 => "ladder.txt",
  2 => "won_rounds.txt",
  3 => "won_matches.txt"
);

$players = array(new player());

$c = 0;
while (isset($servers[$c]))
{
  $d = 0;
  while (isset($types[$d]))
  {
    $file = $servers[$c].$types[$d];
    $filePointer = fopen($file, "r");

    while (!feof($filePointer))
    {
      $line = fgets($filePointer, 30);
      $value = substr($line, 0, strpos($line, " "));
      if ($value >= 0)
      {
        $name = fixName(substr($line, strpos($line, " "), strlen($line)));
        addInfo($name, $d, $value);
      }
    }
    fclose($filePointer);
    $d++;
  }
  $c++;
}

print_r($players);

class player{
    var $name = "";
    var $finalscore = 0;

    var $scores = array(
      0 => 0,
      1 => 0,
      2 => 0,
      3 => 0
    );
    var $onservers = array(
      0 => 1,
      1 => 1,
      2 => 1,
      3 => 1
    );
}

function addInfo($name, $type, $value)
{
  global $players;
  $found = 0;
  for ($c = 0; $c < count($players); $c++)
  {
    if ($players[$c]->name == $name)
    {
      $found = 1;
      $players[$c]->scores[$type] += $value;
      $players[$c]->onservers[$type]++;
      return;
    }
  }

  if ($found == 0)
  {
    $end = count($players);
    $players[$end] = new player();
    $players[$end]->name = $name;
    $players[$end]->scores[$type] += $value;
    $players[$end]->onservers[$type]++;
    return;
  }
}

function fixName($name)
{
  $name = ltrim($name);
  $name = rtrim($name);
//  $name = eregi_replace("<", "<", $name);
//  $name = eregi_replace(">", ">", $name);
  $name = eregi_replace("[\n\t\013\rµ]+", "", $name);
  return $name;
}

?>
Well, I guess this much is open source for now... :). The $servers array is the one you want to change. It has paths to in essence the var/ directories of servers. More than one server can be used. It worked fine when I used a small, small sample... But using it on the real stuff :S. Maybe it got caught up on a file not found or a file read timeout?
Image
User avatar
Lucifer
Project Developer
Posts: 8640
Joined: Sun Aug 15, 2004 3:32 pm
Location: Republic of Texas
Contact:

Post by Lucifer »

ON first glance, i suggest you not use fopen to open this particular file, if it's a http: file, that is. Instead, I'd use file_get_contents, which gets it as a string, iirc. Or an array. If it's a string, you can explode it to an array. (Or use the corresopnding method that gets it as an array) My gut says that fopen expects to return a seekable stream, and nothing you get over http is seekable.

Otherwise I'll try to take a closer look at it tomorrow.
Image

Be the devil's own, Lucifer's my name.
- Iron Maiden
User avatar
Tank Program
Forum & Project Admin, PhD
Posts: 6711
Joined: Thu Dec 18, 2003 7:03 pm

Post by Tank Program »

I've used fgets with URLs before and never had a problem tho :S. Maybe it's just too much data to merge together...
Image
Post Reply