'/rate/:post_type/:post_id/:rating', ); } function index(&$reg, &$req, &$resp) { } //------------------------------------------------- // Rate a thread or a comment. //------------------------------------------------- function rate(&$reg, &$req, &$resp) { $info = &new InformationDisplay($reg, $req, $resp); //-------------------------------------------- // Is this a good or a bad post? //-------------------------------------------- if($req->get('rating') == 'good') { $dir = 1; } else if($req->get('rating') == 'bad') { $dir = -1; } else { $info = &new InformationDisplay($reg, $req, $resp); $info->text('Please specify a valid rating.'); } $post = $req->get('post_type') == 'thread' ? 'thread' : 'comment'; $posts = $post .'s'; $post_id = $post .'_id'; // get the post $finder = &$this->getFinder($posts); $p = &$finder->find($req->get('post_id')); //-------------------------------------------- // Figure out the comment and thread id's. //-------------------------------------------- if($post == 'thread') { $comment_id = 0; $thread_id = $p->getId(); } else { $comment_id = $p->getId(); $thread_id = $p->get('thread_id'); } // get the user $user = &$reg->get('user'); //-------------------------------------------- // Error checking //-------------------------------------------- $author_id = $p->get('user_id'); $is_author = ($user->getId() == $author_id); if($author_id <= K4_GUEST_ID) { $author_is_guest = TRUE; } if($post != 'comment') { //-------------------------------------------- // If this is a thread, loop through the thread authors // to determine if one of them is this user. //-------------------------------------------- $authors = &$p->getAuthors(); while($authors->next()) { $author = $authors->current(); if($author->get('user_id') == $user->getId()) { $is_author = TRUE; } } } //-------------------------------------------- // More error checking... //-------------------------------------------- // make sure we're not a guest and that we have permission to vote if(!$user->canDo('rate', $posts) || $user->get('user_id') == K4_GUEST_ID || $is_author) { $info->display('permsRequired'); } // let's make sure that we've not rated this post yet $finder = &$this->getFinder('post_karma'); $karma = &$finder->findWhere('thread_id=? AND comment_id=? AND user_id=?', array($thread_id, $comment_id, $user->getId())); // this person has voted, those cheaters! if($karma !== NULL) { $info->text('You have already rated this post.'); } //-------------------------------------------- // Figure out the average post risk //-------------------------------------------- if($post == 'thread') { $finder = &$this->getFinder('threads'); $stats = &$finder->selectWhere('SUM(t.karma_risk) AS total_karma_risk_sum, SUM(t.karma_reward) AS total_karma_reward_sum, COUNT(t.thread_id) AS total_thread_count', '', array()); $avg_post_risk = @floatval($stats->get('total_karma_risk_sum') / $stats->get('total_thread_count')); } else { $avg_post_risk = 0.5; } //-------------------------------------------- // Figure out the average user karma //-------------------------------------------- $finder = &$this->getFinder('users'); $stats = &$finder->selectWhere('SUM(karma) AS total_sum_karma, COUNT(user_id) AS total_user_count', '', array()); $avg_usr_karma = @floatval($stats->get('total_sum_karma') / ($stats->get('total_user_count') - 1)); // -1 for guest user //------------------------------------------------- // let's figure out what type of impact this user should have // on this thread //------------------------------------------------- if($avg_usr_karma >= 0) { // this will always be the case unless the db is corrupted or something //------------------------------------------------- // I'm thinking that instead of dividing by the average user karma, I // base it off the number of standard deviations away from the average // karma this user is. //------------------------------------------------- $user_impact = @($user->get('karma') / $avg_usr_karma); } else { // this should never happen, but in the event, their impact will be VERY small $user_impact = $avg_risk / 100; } // if the poster is risking above the average, make each persons // rating worth that much more >:P if($p->get('karma_risk') > $avg_post_risk) { $user_impact = $user_impact * ($p->get('karma_risk') / $avg_post_risk); } // if this is a comment, make the impact half as good/bad if($post == 'comment') { $user_impact = $user_impact / 2; } $user_impact = round($user_impact, 2); $user_impact = $user_impact * $dir; //-------------------------------------------- // By this point, it's ensured that the user impact on the post will never be // as great as the thread's karma risk. This is a good thing. Also, it's probable // that even with insane and crazy numbers in the database, the user impact will // never get above five. However, I might be proven wrong when there are lot's of // users posting and also in the instance of an outlier. //-------------------------------------------- //-------------------------------------------- // now let's figure out what the impact on the poster should // be... Now, I decided that the impact on the poster should // be half of that of the user on the post. I don't know why // I chose 1/2, I just did. //-------------------------------------------- $poster_impact = round($p->get('karma_risk') / 2, 2) * $dir; // Now get the voter's gain.. this is just a base rate based off // of the thread's risk. Nothing interesting to it. $user_gain = round($p->get('karma_risk') / 10, 2); // we will use this finder for the next two queries $finder = &$this->getFinder('users'); // if the poster id isn't a guest, update the poster's karma // TODO:{[Should we modify the karma of all of the authors of this thread?[rate[KarmaController} if(!$author_is_guest) { $poster = &$finder->find($author_id); // this will only happen if the poster has disappeared from the database... if($poster !== NULL) { $poster->set('karma', round($poster_impact + $poster->get('karma'), 2)); $poster->save(); } } // update this user's karma assuming this person isn't a guest if($user->get('user_id') > 1) { $u = &$finder->find($user->get('user_id')); $u->set('karma', round($user_gain + $u->get('karma'), 2)); $u->save(); } // update this post's karma $p->set('karma_reward', round($p->get('karma_reward') + $user_impact, 2)); $p->save(); //-------------------------------------------- // if we're rating a comment, make the rating of this comment SLIGHTLY affect the // rating of the thread. Why? Well, if a comment is good/bad, it makes the thread // that much better/worse. // ** // still not too sure about this because this would mean that you can up or down // the karma of your own thread indirectly. Though by not ver much, it can still // make a difference. // ** //-------------------------------------------- if($post == 'comment') { $finder = &$this->getFinder('threads'); $thread = &$finder->find($thread_id); $thread->set('karma_reward', $thread->get('karma_reward') + ($user_impact / 1.5)); $thread->save(); } //-------------------------------------------- // Add the entry to the karma records //-------------------------------------------- $finder = &$this->getFinder('post_karma'); $karma = &$finder->createRecord(); $karma->set('thread_id', $thread_id); $karma->set('comment_id', $comment_id); $karma->set('user_id', $user->get('user_id')); $karma->set('rate_val', $user_impact); $karma->set('rate_time', time()); $karma->save(); //-------------------------------------------- // A nice path for the referer. //-------------------------------------------- if($post == 'comment') { $referer = '/thread/'. $p->get('thread_id') .'/'; } else { $referer = '/thread/'. $p->getId() .'/'. k4_us($p->get('name')) .'/'; } $info->text('Thank you for rating this post.', $referer, 3); } } ?>