See

http://www.webcodr.com/4/writing-a-digg-style-popularity-algorithm/

I'am not familiar with voting api today, but this algorithm looks fairly interesting.

I don't have the time, nor the knowledge to make this. But anyone who can, feel free to start hacking out a digg/reddit clone;)

eg. votingstyle is: Popularity = Votes / Record Age

But check out the link I provided to get a more in depth understanding.

Comments

stephencarr’s picture

Without something like this I find that most of the modules that use voting API are kind of useless in terms of displaying popular content. We can pretty much only display which content has the most votes filtered by very ordinary things like time, user etc. etc. I am surprised less people are interested in a more algorithmic way of sorting nodes.

Scott Reynolds’s picture

This algorithm has actually been implemented on http://www.momblognetwork.com

the code that does it is run at cron time and it is this:

/**
 * This private function calculates the popularity score
 * and inserts it into the votingapi cache table
 * by calling _votingapi_insert_cache_result
 */
function _popularity_calculate($votes, $content_id, $created, $target_time) {

  //go through each vote and calcualte the total
  $total = 0;
  $has_votes = false;

  foreach ($votes as $vote) {
    if ($vote->value_type == 'points' && $vote->timestamp <= $target_time) {
      // get the weight of the user
      $weight = _popularity_user_weight($vote->uid);
      $total += ($vote->value * $weight) / ( (.7 * ($target_time - $vote->timestamp)) + 1 );
      $has_votes = true;
    }
  }
  // this was necessary because if it doesn't have votes we don't want it to have
  // a popularity
  if ($has_votes) {
    // insert score into votingapi_cache table
    _votingapi_insert_cache_result('node', $content_id, $result, 'points', 'vote', 'popularity');
  }
}
stephencarr’s picture

Hi Scott, good to hear that there is a way ahead. Could you maybe explain how this can be integrated with a generic site using the voting api? I am not really sure how I can get this code to run at cron and how I can take advantage of the data it saves, in other words how do I integrate it with a view generated or templated page?

Many thanks.

Scott Reynolds’s picture

Create a module and call that function on its hook_cron.

Then votingapi will add the filter, arguments etc to views with a score title popularity. Votingapi takes care of all the views for you, just create a module that calculates the popularity score.

Scott Reynolds’s picture

and if that doesn't make sense to you use Drigg: http://drupal.org/project/drigg

stephencarr’s picture

Thanks very much! I looked at Drigg a while back but for some reason passed it over. I think I will be having another look or perhaps try writing a module of my own and implementing your code, always willing to learn more.

stephencarr’s picture

The function you listed above is missing the _popularity_user_weight() function definition, I'd be interested in how that works. Also I am not certain but isn't _votingapi_insert_cache_result() a private function of the votingapi and therefore not accessible from another module?

Scott Reynolds’s picture

yes it is missing that function, i forgot to take that line out. Sorry ;) thats our secret sauce. I should have replaced it with a 1.

as far as 'private' goes, there is no 'private' functions in drupal. They are written that way to indicate that they shouldn't be used by outside modules but clearly this is a instance where its needed.

You could, instead of calling that function, insert the record directly into the table.

eaton’s picture

Status: Postponed (maintainer needs more info) » Closed (won't fix)

Support for the 5.x branch of VotingAPI has ended with the release of Drupal 7 and the upcoming release of VotingAPI 7.x-2.4.