Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

A ladder system, for those of you who don't know, is where objects sit on "rungs" which determine their "score". Example, #1 rung is the highest spot. A lower rung that beats a higher rung (in whatever is being ranked) takes the higher rung's place, and the higher rung moves down x% of the total rungs.

How would one implement this efficiently in Perl? I am planning on using mySQL for the data storage, and was considering having a "rung" field. After thinking about this, I came to the conclusion that I'd need to modify lots and lots of fields to decrement their rung number if another object moved ahead. I eventually decided that the most efficient way would be to have a plaintext file with a unique identifier for each object stored with lines as their respective rungs. (ie: first line would be the first rung, 5th line would be the fifth rung, etc.) Then changing every rung's number would not be so intensive.

After thinking on this flattext + mySQL method, I decided I might as well be shooting myself in the foot. What would you monks recommend doing to keep track of rungs, preferrably staying away from a flattext list?

Thanks;

Replies are listed 'Best First'.
Re: Implementation of a Ladder System
by cLive ;-) (Prior) on May 11, 2001 at 23:54 UTC

    I would suggest you read this and this to get you started.

    cLive ;-)

    Update: of course, it depends on how you run it. If users 'play each other' and highest swops down if they lose, then a hash would be easiest, eg:

    # (snippet) my %player = ( joe => 1, jay => 2, jak => 3, jim => 4); # Say jim beat jak, then you just need to reassign $winner = 'jim'; $loser = 'jak'; if ($player{$winner} < $player{$loser}) { ($player{$winner},$player{$loser}) = ($player{$loser},$player{$winne +r}); } # then rewrite your hash to db
      That would involve a flattext file, as per my post. I was trying to stay away from that. Thanks though,
      -I
        why? flat text is just another database. If it can be stored in flat text, it can be stored in DB.

        .02

        cLive ;-)

Re: Implementation of a Ladder System
by princepawn (Parson) on May 12, 2001 at 00:09 UTC
Re: Implementation of a Ladder System
by mr.nick (Chaplain) on May 12, 2001 at 00:56 UTC
    I think an important question for this is how many users are we talking about? If it's sufficiently small, I think the question to ask is "Do I need to pregenerated the ladder, or have it dynamically built as needed?".

    If your ladder is simply a ranking of people based on a simple equation (ie, "score" as in your example, a single value) then generating a 50 rung ladder could be as simple as

    select id,score from table order by score desc limit 50;
    in SQL which would return a list of the top 50 rung members. Implementation via DBI I'll leave to the reader.

    Even if the equation is complex, it still may be doable on-the-fly using joins, math functions, and other features of SQL.

    But this method may not be fast enough if your database is of sufficient size. It's a balancing act.

Re: Implementation of a Ladder System
by tune (Curate) on May 11, 2001 at 23:46 UTC
    If you have a large amount of users, the best solution should be to generate the ladder on a timely basis (cron) into another Mysql table. I think it is an easy query usually.
    That table should contain only the username and the rung column with an index for username, so it could be handled very fastly.

    --
    tune

Re: Implementation of a Ladder System
by steveAZ98 (Monk) on May 12, 2001 at 00:11 UTC
    I think I would handle it with a couple of tables. One for the users information and another table with a column for a Storable serialized object. I would create a datastructure with the rankings of the users and then store it to the database. The next time through I would retrieve that data structure, reorder however necessary and then store it back. You can use that datastructure to order (rank) your users and it only requires one update and one select for the ordering. I'm not sure how many user id's you could store in a single field, it would depend I guess on what you stored in your data structure. This would remove the flat file and would probably increase your performance. I haven't used this for anything myself as of yet, but it seems like it might be a good way to do what your looking for.

    HTH,
    Steve
Re: Implementation of a Ladder System
by Banky (Acolyte) on May 12, 2001 at 01:39 UTC
    My initial thought would be just keeping a score field in your database and doing an order by. Like MrNick said this would work well for reasonably sized data sets. The part that gets tricky is when a higher rung moves down x% of the total rungs. This would involve changing the score to a number between the scores of the correct rungs. Important details I would like to have:
  • Number of players
  • How a player beats another player
  • What information you're keeping track of in terms of rating and score

    An array might be a good way of holding your items. If you tied the array to keep it flushed to disk that might another way of handling it.

Re: Implementation of a Ladder System
by eejack (Hermit) on May 12, 2001 at 05:27 UTC

    A somewhat different approach.

    Let's generate the ladder off a mysql database on the fly and update on the fly.
    I'd have one table with all the user info (name, etc.) and a ladder table with two fields, user_id and ladder.
    :ladder_table +------------+-------------+ | Field | Type | +------------+-------------+ | user_id | smallint(6) | | ladder_id | smallint(6) | +------------+-------------+


    When you have a situation where user_id 0034 (current ladder ranking of 2345) beats user_id 0638 (current_ladder ranking of 7) you know that the only users who will be affected are those whose ladder ranking is between 7 and 2345.

    You can do this in three sql calls.

    Your first sql call would clear the winner out of the way.
    DELETE from ladder_table where ladder_id = 2345

    Then you need to determine how many user_id 0638 is going to fall (through whatever method you come up with). I am going to assume this user is falling ten rankings for this example. This will be necessity shove everyone from ladder_ranking 17 to ladder_ranking 2344 down as well.
    UPDATE ladder_table SET ladder_ranking = ladder_ranking -1 WHERE ladder_ranking >= 17 AND ladder_ranking < 2345

    The last one is the call setting your user_id 0034 to the ranking of 7.

    UPDATE ladder_table SET ladder_ranking = 7 WHERE user_id = 0034


    Those calls should be very fast in most cases.
    Thanks,

    EEjack

Re: Implementation of a Ladder System
by Anonymous Monk on May 12, 2001 at 03:30 UTC
    Do a search for Linked lists and double linked lists.

    You may be able to do something like this.

    Add two fields to your DB. These fields hold the Primary ID of the records on either side of the current record.

    DB Feilds

    (RECORDID ;INFO ;NEXT ;PREVIOUS) (5 ;anything ;6 ;4) (6 ;anything ;7 ;5) (7 ;anything ;8 ;6) (8 ;anything ;9 ;7)

    Now if you need to move record 5 between 7 and 8 the only records you need to alter are the Next and Previous fields of record 4,5,6,7,8 or if you want to move 5 between 500 and 501 you will only have to change 4,5,6,500,501. You can then index and sort based on the Next and Previous fields. Just my 2 cents