How would I add a users rank in their profile... say user A had the most points on the site and I wanted to display something like "User A: Rank 1" and so on for each members profile.

Thanks in advance...

Comments

ibexy’s picture

I think the Advanced Profile Kit does that automatically: http://drupal.org/project/advanced_profile

kbahey’s picture

No, the advanced profile does not provide ranking. I just looked at the code, and it only displays the user's points.

To do ranking, you need some custom code.

You can already do things like Top 5 users like so:

// If using categories
$sql = 'SELECT p.uid, u.name, p.points
  FROM {userpoints} p
  INNER JOIN {users} u USING (uid)
  WHERE p.tid = 0 OR p.tid IS NULL ORDER BY p.points DESC';
$result = db_query_range($sql, 0, 5);

// Or to be minimalistic, assuming you already have the name of the user
$sql = 'SELECT p.uid, p.points
  FROM {userpoints} p
  WHERE p.tid = 0 OR p.tid IS NULL ORDER BY p.points DESC';
$result = db_query_range($sql, 0, 5);
// If you are not using categories
$sql = 'SELECT p.uid, u.name, p.points
  FROM {userpoints} p
  INNER JOIN {users} u USING (uid)
  WHERE p.tid = %d ORDER BY p.points DESC';
$result = db_query_range($sql, $tid, 0, 5);

// Or to be minimalistic, assuming you already have the name of the user
$sql = 'SELECT p.uid, p.points
  FROM {userpoints} p
  WHERE p.tid = %d ORDER BY p.points DESC';
$result = db_query_range($sql, $tid, 0, 5);

You can expand that to getting rank for each users. You need to cache this somewhere, since running the query too often can be expensive.

walker2238’s picture

Hmmm... This request seems to be a bit over my head. I have a fair concept of the above code, but as far a the cache is concerned you lost me. I understand the query thing I think as you suggest that I wouldn't want to have real time updates, Ie.. Database query everytime the page is loaded??? My main problem is trying to figure out how to rank the users in relation to the users total user points.

jredding’s picture

There is all the top_contributers module over in userpoints_contributed modules that does something similar. Maybe it would be close enough so you wouldn't have to dive into the code? don't know..

walker2238’s picture

Yeah I looked into that, however from my understanding of that module the rank is in association with the list of users. So it really acts more like a ordered list then actually ranking the users. So the output is just numbered. I'd really like to have this feature select where the user ranks among other users. The above code is a good starting point but it's just a matter of how to figure out where a user ranks among other users. So say as a alternative (That would serve no purpose to me) I would print the users total points on the page. say user A had 115 total points. Seems simple enough. But now to figure out how to go that extra step by figuring where does that 115 points rank among other points within the point structure of the database.

Does that make sense?

kbahey’s picture

For caching, what you need to do is something like this:

$rank = 0;
while ($row = db_fetch_object($result)) {
  $rank++;
  $rank_data = $rank . ':' . $row->points; // Rank and number of points
  $data = serialize($rank_data); 
  cache_set('userpoints_rank:' . $row->uid, 'cache', $data);
}

This stores the number of points and the rank in the cache.

To retrieve this, you do something like this:

  // Check the cache, to see if the stuff is stored there

  if ($data = cache_get('userpoints_rank:' . $uid, 'cache')) {
    $rank_data = unserialize($data);
    list($rank, $points) = explode(':', $rank_data);
  }
  else {
    // do the db queries
  }
}

This way, you don't have to do the entire ranking every time to you want to show it and it can stay in the cache for sometime.

Check http://api.drupal.org/api/function/cache_set/5 for more info on how long you can keep stuff in the cache, and such.

You can even do that in cron, so it is calculated every hour or every day.

walker2238’s picture

Well kbahey nothing so far. I tried messing with the bits of code you suggested and nothing seems to work so far.

kbahey’s picture

This is not final working code.

It is just the parts that you need to put in a module to get the functionality you want. It needs to be fleshed out.

If you are not a developer, then please ignore the code I posted. Someone else who may be interested can write the module.

walker2238’s picture

Well I've only been learning ph for a few months so a developer I am not. I understood though that the code you showed me would not give me results as you were just trying to point me in the right direction. So far I figured out how to give the users various titles with something like this...

$user_points = userpoints_get_current_points($user->uid);
if ($user_points >= 25 && $user_points <= 50) {
$user_rank = 'Try harder cause you suck!';
} 
if ($user_points >= 51 && $user_points <= 100) {
$user_rank = 'Atleast your better then the other guy';
} 
if ($user_points >= 101) {
$user_rank = 'Your officially the coolest guy on the internet';
} 
print '<p>' . $user_rank . '</p>';

Although this isn't what I wanted, I'll have to settle for this for the time being.

Is the above code ok? Or should I be using switch statements of elseif's?

kbahey’s picture

That is not ranking. Ranking means the user gets a number from 1 to N, based on how many points they have.
If you said so from the start, we would have given you a proper answer sooner.

What you want is something similar to User badges http://drupal.org/project/user_badges or User titles http://drupal.org/project/user_titles

You can see which one is best for your case, then integrate it with userpoints.

For some starting code, check the userpoints_role in the userpoints_contrib project. Just change it to assign a badge/title instead of a role.

walker2238’s picture

No sorry ranking is what I want. I was just showing what I'm using as a fill in for now. Not sure why I even posted it as it doesn't have much to do with the question I posted. Sorry for the confusion. I think it's best if I stop posting and just wait and see if anyone with better skills than I.

jredding’s picture

Are you sure that the top contributors module doesn't do what you want?
http://drupal.org/project/userpoints_top_contributors

if not if you could you explain why it doesn't do what you want maybe we can help you along.

walker2238’s picture

jredding I really do appreciate your patience and help. The reason that the top contributors module does not fit my needs is because it creates a page on the top users which are then ordered on a page. From my knowledge (I tried it briefly before) it creates a list which is not really a rank because it just orders the users by points along with a number for each row.

The difference with that module and what I'd like to do is that I only want the rank for one user. Whichever users profile is being viewed.

jredding’s picture

Isn't a list of user's by their user points a ranking?

What I'm getting at is the top contributors module gives you what you want in a different way. You want to know if Joe is number #8 or number #10 in regards to his numbers of points relative to all other users on the site.

I downloaded and took a look at the top contributors module and the DB looks like this.

     uid INT(10),
     rank INT(10),
     period_points FLOAT(10,1),
     current_points FLOAT(10,1),
     lifetime_points FLOAT(10,1),

It also provides information on the profile page about the user but doesn't provide the user's rank. From a 5 second look at the code it seems like it something like

  global $user; 
  $sql = "SELECT rank FROM {userpoints_top_contributors} where uid = %d":
  $rank  = db_result(db_query($sql, $user->uid));

When displaying the user's profile page would add in the information you want.

So again I'm highly suggesting you take a look at this module.

walker2238’s picture

Well guess your right. I'll download it again... I never did look at the database. From the above code could I not just write something like

$user_rank = db_result(db_query("SELECT rank FROM {userpoints_top_contributors} where uid = %d", $user->uid));

Or is your way more efficient?
Anyways I'll give it a try and let you know how it works out.

jredding’s picture

they are both the same.

walker2238’s picture

You were right... I should have listened earlier instead of assuming... Thank you very much as this is a main feature that I almost gave up on...

berdir’s picture

Status: Active » Closed (won't fix)

Sorry for spamming the participants in this issue. Due to the release of Drupal 7 and the lack of time from the maintainers, I'm closing all remaining 5.x issues for Userpoints.

Feel free to re-open this issue or create a new one for 6.x or even better 7.x if this bug is still open or feature is missing for these versions.