I was thinking, despite users have the option of create their own buddy groups, it would be great if they could assign a level of buddy-ism to any on of their buddies. Something like, from 1 to 10:

1: best buddyes, family, i´ll die for him.
2: very good friends..
3: etc..
...
10: Barely know him/her

Of course the descriptions could be configurable by admins and the number of levels.

Now you may be wondering what is the benefit of this. Well, it's very simple. My goal is to show on a page or on the user profile page a view of the user "network". Plus, when a user is viewing other user's profile he/her will see a graph with the shortest path to that user through it's network, in case that user is reachable (both have other users as buddies, on first, second, n-level). This would be calculated using a Dijkstra algorithm.

The way it is designed all buddy connections will have the same level or weight. If we add this weight or level to the buddy table per every connection, Dijkstra algorithm will return the shortest path to any user, which means also those will be the stronger buddy connections.

I have plans to start working on this Dijkstra algorithm implementation, although it doesn't have to be integrated on the Buddy module (but it could). But I would like to have the weight-level system integrated.

What do you guys think?

Comments

fago’s picture

imho there is already a lot of functionality built into buddylist and I see the danger of a big difficult to maintain module. So I would appreciate further splits into smaller modules that work together.

So I would like to see this as an addition to buddylist, so that the level of "buddy-ism" can be optionally enabled by using its module. Of course we can integrate necessary changes into buddylist itself, so that the buddy-ism module can add table columns and so on as appropriate.

The shortest path feature is really nice and I think often requested. Imho best this would also be also another addition to buddylist - not depending at the buddy-ism module. If it's not activated, the shortest path could just be calculated by using a default buddy-ism of 1 for every buddy.

It would be really cool if you could contribute that!

EnekoAlonso-1’s picture

I agree!

I don't use most of the stuff included on buddylist modules, like groups (although if these could be defined only by administrators, that could solve the level of buddy-ism.

Right now I haven't had time to figure out how to do this on a module, so I just wrote the code to solve the shortest path between two users urign Dijkstra algorithm. Here it is:


/* Dijstra algorithm */
function spaniards_getbuddypath($startid, $finalid)
{
	// Load vertex (users) map
  $users = array();
  // Users with buddies
  $result = db_query("select distinct uid from buddylist");
  while ($usr = db_fetch_object($result)) {
    $users[$usr->uid] = $usr->uid;
  }
  // Users without buddies but which are buddies of somebody
  $result = db_query("select distinct buddy as uid from buddylist");
  while ($usr = db_fetch_object($result)) {
  	if (!isset($users[$usr->uid]))
  	  $users[$usr->uid] = $usr->uid;
  }
  if (!isset($users[$startid])) return array();
  if (!isset($users[$finalid])) return array();

  $infinity = 999999999; // Make this number bigger than the total of users * highest weight
  $distance = array();
  $userpred = array();
  $paths    = array();

  // Initialize vertex arrays
  foreach($users as $uid) {
    $distance[$uid] = $infinity;
    $userpred[$uid] = 0;
    $paths[$uid]    = array();
  }

  // Load all paths
  $result = db_query("select uid, buddy, 1 as weight from buddylist order by uid, buddy");
  while ($relation = db_fetch_object($result)) {
  	$paths[$relation->uid][$relation->buddy] = $relation->weight;
  }

  // Set starting point
  $distance[$startid] = 0;

  // Process all vertex (users)
  while (count($users) > 0)
  {
    // Calculate the closest user and extract it from the array
    $closestid   = 0;
    $closestdist = $infinity;
    foreach($users as $uid) {
      if ($distance[$uid] <= $closestdist) {
        $closestdist = $distance[$uid];
        $closestid = $uid;
      }
    }
  	$baseid = $users[$closestid];
  	unset($users[$closestid]);

  	if ($baseid == $finalid) break;

    // Process paths for the closest user
    $emanatingpaths = $paths[$baseid];
    foreach ($emanatingpaths as $currentid => $weight) {
      if (in_array($currentid, $users)) {
        if ($distance[$baseid] + $weight < $distance[$currentid]) {
          $distance[$currentid] = $distance[$baseid] + $weight;
          $userpred[$currentid] = $baseid;
        }
      }
    }
  }

  // Read the path backwards, from finalid to startid
  $shortpath = array();
  if ($distance[$finalid] < $infinity) {
    $buddyid = $finalid;
    while ($buddyid > 0) {
      array_unshift($shortpath, $buddyid); // insert new buddy at the beginning
      $buddyid = $userpred[$buddyid];
    }
  }
  return $shortpath;
}


If anybody is interested, feel free to use it or to put it on a module. Or if anybody wants to explain me how to do that, that would be nice.

You can see the result of this code on my webpage, here:
http://www.spaniards.es/node/2420

I'm sorry but only registered users can see it working on their profiles.

Thanks.

EnekoAlonso-1’s picture

The link I posted before is a link to a screenshot. You can see it on Flickr too:
http://www.flickr.com/photos/eneko/423337561/

PS: I bet this code doesn't follow any Drupal coding standars but that's up to you if you want to use it :)

Thanks.

jbhan’s picture

would this work in 4.7? or is it 5.0 specific?

j