Fix a bug where ratings were allowed to be set with less than 10 votes. Fixes bug #11294

This helps fix people trying to game the system.
This commit is contained in:
Colin Kuskie 2009-12-08 14:39:24 -08:00
parent 5153d82327
commit d1e6f30493
5 changed files with 253 additions and 94 deletions

View file

@ -3,6 +3,7 @@
- fixed #11292: Search function limited to onje search?
- fixed #11286: Workflow Instance deleted when reaching an Activity that fails to load
- fixed #11296: listLDAPLinks op permissions problems
- fixed #11294: Matrix - Best/Worse Rated Calculations
7.8.7
- fixed #11278: Wrong test for Template::Toolkit in testEnvironment.pl

View file

@ -32,6 +32,7 @@ my $session = start(); # this line required
# upgrade functions go here
deleteFieldFromEMSSubmission($session);
tenVoteMinimumForMatrixRatings($session);
finish($session); # this line required
@ -60,6 +61,15 @@ ENDSQL
print "DONE!\n" unless $quiet;
}
#----------------------------------------------------------------------------
# Describe what our function does
sub tenVoteMinimumForMatrixRatings {
my $session = shift;
print "\tRestrict Matrix Listing Statistics to those with more than 10 ratings..." unless $quiet;
$session->db->write('update MatrixListing_ratingSummary set meanValue=0, medianValue=0 where countValue < 10');
print "\tDONE!\n" unless $quiet;
}
# -------------- DO NOT EDIT BELOW THIS LINE --------------------------------
#----------------------------------------------------------------------------

View file

@ -608,9 +608,11 @@ sub setRatings {
my $mean = $sum / ($count || 1);
my $median = $db->quickScalar("select rating $sql order by rating limit $half,1",[$self->getId,$category]);
$db->write("replace into MatrixListing_ratingSummary
(listingId, category, meanValue, medianValue, countValue, assetId)
values (?,?,?,?,?,?)",[$self->getId,$category,$mean,$median,$count,$matrixId]);
if ($count >= 10) {
$db->write("replace into MatrixListing_ratingSummary
(listingId, category, meanValue, medianValue, countValue, assetId)
values (?,?,?,?,?,?)",[$self->getId,$category,$mean,$median,$count,$matrixId]);
}
}
return undef;
}

View file

@ -631,16 +631,11 @@ sub view {
$style->setLink($url->extras('yui/build/datatable/assets/skins/sam/datatable.css'),
{type =>'text/css', rel=>'stylesheet'});
$style->setScript($url->extras('yui/build/utilities/utilities.js'),
{type => 'text/javascript'});
$style->setScript($url->extras('yui/build/json/json-min.js'),
{type => 'text/javascript'});
$style->setScript($url->extras('yui/build/datasource/datasource-min.js'),
{type => 'text/javascript'});
$style->setScript($url->extras('yui/build/datatable/datatable-min.js'),
{type => 'text/javascript'});
$style->setScript($url->extras('yui/build/button/button-min.js'),
{type => 'text/javascript'});
$style->setScript($url->extras('yui/build/utilities/utilities.js'), {type => 'text/javascript'});
$style->setScript($url->extras('yui/build/json/json-min.js'), {type => 'text/javascript'});
$style->setScript($url->extras('yui/build/datasource/datasource-min.js'), {type => 'text/javascript'});
$style->setScript($url->extras('yui/build/datatable/datatable-min.js'), {type => 'text/javascript'});
$style->setScript($url->extras('yui/build/button/button-min.js'), {type => 'text/javascript'});
my ($varStatistics,$varStatisticsEncoded);
my $var = $self->get;
@ -763,7 +758,7 @@ sub view {
push (@{ $varStatistics->{last_updated_loop} }, {
url => $lastUpdatedListing->getUrl,
name => $lastUpdatedListing->get('title'),
lastUpdated => $self->session->datetime->epochToHuman($lastUpdatedListing->get('lastUpdated'),"%z")
lastUpdated => $session->datetime->epochToHuman($lastUpdatedListing->get('lastUpdated'),"%z")
});
}
$varStatistics->{lastUpdated_sortButton} = "<span id='sortByUpdated'><button type='button'>"
@ -806,21 +801,21 @@ sub view {
$data = $db->quickHashRef($sql." desc limit 1",[$category,$self->getId]);
push(@{ $varStatistics->{best_rating_loop} },{
url=>'/'.$data->{url},
category=>$category,
name=>$data->{productName},
mean=>$data->{meanValue},
median=>$data->{medianValue},
count=>$data->{countValue}
url => $session->url->gateway($data->{url}),
category => $category,
name => $data->{productName},
mean => 0+$data->{meanValue},
median => 0+$data->{medianValue},
count => 0+$data->{countValue}
});
$data = $db->quickHashRef($sql." asc limit 1",[$category,$self->getId]);
push(@{ $varStatistics->{worst_rating_loop} },{
url=>'/'.$data->{url},
category=>$category,
name=>$data->{productName},
mean=>$data->{meanValue},
median=>$data->{medianValue},
count=>$data->{countValue}
url => $session->url->gateway($data->{url}),
category => $category,
name => $data->{productName},
mean => 0+$data->{meanValue},
median => 0+$data->{medianValue},
count => 0+$data->{countValue}
});
}

View file

@ -17,7 +17,7 @@ use lib "$FindBin::Bin/../../lib";
use WebGUI::Test;
use WebGUI::Session;
use Test::More tests => 26; # increment this value for each test you create
use Test::More tests => 30; # increment this value for each test you create
use Test::Deep;
use JSON;
use WebGUI::Asset::Wobject::Matrix;
@ -65,13 +65,13 @@ cmp_deeply (
# Test add/edit privileges
is ($matrix->canEdit,'0',"Checking canEdit privilege");
is ($matrix->canAddMatrixListing,'0',"Checking canAddMatrixListing privilege");
ok !$matrix->canEdit, "canEdit: as Visitor cannot edit";
ok !$matrix->canAddMatrixListing,"canAddMatrixListing: as Visitor cannot add matrix listing";
$session->user({userId => 3});
is ($matrix->canEdit,'1',"Checking canEdit privilege as Admin");
is ($matrix->canAddMatrixListing,'1',"Checking canAddMatrixListing privilege as Admin");
ok $matrix->canEdit, "canEdit: as Admin can edit";
ok $matrix->canAddMatrixListing, "canAddMatrixListing: as Admin can add matrix listing";
# add a new attribute
@ -87,7 +87,7 @@ my $newAttribute = $matrix->getAttribute($newAttributeId);
my $isValidId = $session->id->valid($newAttributeId);
is($isValidId,1,"editAttributeSave returnes a valid guid");
ok $isValidId, "editAttributeSave returnes a valid guid";
is($newAttribute->{name},'test attribute',"Adding a new attribute, attribute name was set correctly");
is($newAttribute->{fieldType},'MatrixCompare',"Adding a new attribute, undefined fieldType was set correctly to default value");
@ -115,13 +115,13 @@ isa_ok($matrixListing, 'WebGUI::Asset::MatrixListing');
is($matrixListing->getAutoCommitWorkflowId,undef,"The matrix listings getAutoCommitWorkflowId method correctly returns undef, because the auto commit workflow should only be used on adding a new matrix listing.");
#is($matrixListing->hasRated,'0',"The matrix listings hasRated method returns correct value.");
ok( !$matrixListing->hasRated, "hasRated returns false since user hasn't rated yet");
$matrixListing->setRatings({category1=>'1',category2=>'10'});
$matrixListing->setRatings({category1=>'1',category2=>'9'});
ok($matrixListing->hasRated > 0,"Checking hasRated method after rating.");
ok($matrixListing->hasRated, "hasRated returns true after user has rated");
$matrixListing->setRatings({category1=>'2',category2=>'5'});
$matrixListing->setRatings({category1=>'3',category2=>'5'});
$matrixListing->www_click;
@ -177,7 +177,6 @@ cmp_deeply(
$session->user({userId => 3});
my $json = $matrix->www_getCompareFormData('score');
note $session->getId;
my $compareFormData = JSON->new->decode($json);
@ -230,66 +229,218 @@ cmp_deeply(
# Test statistics caching by view method
WebGUI::Cache->new($session,"matrixStatistics_".$matrix->getId)->delete;
$matrix->view;
my $varStatisticsEncoded = WebGUI::Cache->new($session,"matrixStatistics_".$matrix->getId)->get;
my $varStatistics = JSON->new->decode($varStatisticsEncoded);
cmp_deeply(
$varStatistics,
{
alphanumeric_sortButton=>"<span id='sortByName'><button type='button'>Sort by name</button></span><br />",
bestViews_url=>'/'.$matrixListing->get('url'),
bestViews_count=>1,
bestViews_name=>$matrixListing->get('title'),
bestViews_sortButton=>"<span id='sortByViews'><button type='button'>Sort by views</button></span><br />",
bestCompares_url=>'/'.$matrixListing->get('url'),
bestCompares_count=>1,
bestCompares_name=>$matrixListing->get('title'),
bestCompares_sortButton=>"<span id='sortByCompares'><button type='button'>Sort by compares</button></span><br />",
bestClicks_url=>'/'.$matrixListing->get('url'),
bestClicks_count=>1,
bestClicks_name=>$matrixListing->get('title'),
bestClicks_sortButton=>"<span id='sortByClicks'><button type='button'>Sort by clicks</button></span><br />",
last_updated_loop=>[{
url => $matrixListing->getUrl,
name => $matrixListing->get('title'),
lastUpdated => $session->datetime->epochToHuman($matrixListing->get('lastUpdated'),"%z")
}],
lastUpdated_sortButton=>"<span id='sortByUpdated'><button type='button'>Sort by updated</button></span><br />",
best_rating_loop=>[{
url=>'/'.$matrixListing->get('url'),
category=>'category1',
name=>'untitled',
mean=>'1.50',
median=>2,
count=>2,
},
{
url=>'/'.$matrixListing->get('url'),
category=>'category2',
name=>'untitled',
mean=>'7.50',
median=>10,
count=>2,
}],
worst_rating_loop=>[{
url=>'/'.$matrixListing->get('url'),
category=>'category1',
name=>'untitled',
mean=>'1.50',
median=>2,
count=>2,
},
{
url=>'/'.$matrixListing->get('url'),
category=>'category2',
name=>'untitled',
mean=>'7.50',
median=>10,
count=>2,
}],
listingCount=>1,
$varStatistics,
{
alphanumeric_sortButton=>"<span id='sortByName'><button type='button'>Sort by name</button></span><br />",
bestViews_url=>'/'.$matrixListing->get('url'),
bestViews_count=>1,
bestViews_name=>$matrixListing->get('title'),
bestViews_sortButton=>"<span id='sortByViews'><button type='button'>Sort by views</button></span><br />",
bestCompares_url=>'/'.$matrixListing->get('url'),
bestCompares_count=>1,
bestCompares_name=>$matrixListing->get('title'),
bestCompares_sortButton=>"<span id='sortByCompares'><button type='button'>Sort by compares</button></span><br />",
bestClicks_url=>'/'.$matrixListing->get('url'),
bestClicks_count=>1,
bestClicks_name=>$matrixListing->get('title'),
bestClicks_sortButton=>"<span id='sortByClicks'><button type='button'>Sort by clicks</button></span><br />",
last_updated_loop=>[{
url => $matrixListing->getUrl,
name => $matrixListing->get('title'),
lastUpdated => $session->datetime->epochToHuman($matrixListing->get('lastUpdated'),"%z")
}],
lastUpdated_sortButton=>"<span id='sortByUpdated'><button type='button'>Sort by updated</button></span><br />",
best_rating_loop=>[{
url => '/',
category=> 'category1',
name => undef,
mean => 0,
median => 0,
count => 0,
},
'Statistics were cached by view method.'
);
{
url => '/',
category=> 'category2',
name => undef,
mean => 0,
median => 0,
count => 0,
}],
worst_rating_loop=>[{
url => '/',
category=> 'category1',
name => undef,
mean => 0,
median => 0,
count => 0,
},
{
url => '/',
category=> 'category2',
name => undef,
mean => 0,
median => 0,
count => 0,
}],
listingCount=>1,
},
'Statistics were cached by view method.'
);
##Now, add a bunch of ratings. Each one has two
$matrixListing->setRatings({category1=>'1',category2=>'9'});
$matrixListing->setRatings({category1=>'3',category2=>'5'});
$matrixListing->setRatings({category1=>'1',category2=>'9'});
$matrixListing->setRatings({category1=>'3',category2=>'5'});
$matrixListing->setRatings({category1=>'1',category2=>'9'});
$matrixListing->setRatings({category1=>'3',category2=>'5'});
$matrixListing->setRatings({category1=>'1',category2=>'9'});
WebGUI::Cache->new($session,"matrixStatistics_".$matrix->getId)->delete;
$matrix->view;
my $varStatisticsEncoded = WebGUI::Cache->new($session,"matrixStatistics_".$matrix->getId)->get;
my $varStatistics = JSON->new->decode($varStatisticsEncoded);
cmp_deeply(
{
best_rating_loop => $varStatistics->{best_rating_loop},
worst_rating_loop => $varStatistics->{worst_rating_loop},
},
{
best_rating_loop => [{
url => '/',
category=> 'category1',
name => undef,
mean => 0,
median => 0,
count => 0,
},
{
url => '/',
category=> 'category2',
name => undef,
mean => 0,
median => 0,
count => 0,
}],
worst_rating_loop => [{
url => '/',
category=> 'category1',
name => undef,
mean => 0,
median => 0,
count => 0,
},
{
url => '/',
category=> 'category2',
name => undef,
mean => 0,
median => 0,
count => 0,
}],
},
'With only 9 ratings, still no statistics'
);
WebGUI::Cache->new($session,"matrixStatistics_".$matrix->getId)->delete;
$matrixListing->setRatings({category1=>'3'});
$matrix->view;
my $varStatisticsEncoded = WebGUI::Cache->new($session,"matrixStatistics_".$matrix->getId)->get;
my $varStatistics = JSON->new->decode($varStatisticsEncoded);
cmp_deeply(
{
best_rating_loop => $varStatistics->{best_rating_loop},
worst_rating_loop => $varStatistics->{worst_rating_loop},
},
{
best_rating_loop => [{
url => '/'.$matrixListing->get('url'),
category=> 'category1',
name => 'untitled',
mean => 2,
median => 3,
count => 10,
},
{
url => '/',
category=> 'category2',
name => undef,
mean => 0,
median => 0,
count => 0,
}],
worst_rating_loop => [{
url => '/'.$matrixListing->get('url'),
category=> 'category1',
name => 'untitled',
mean => 2,
median => 3,
count => 10,
},
{
url => '/',
category=> 'category2',
name => undef,
mean => 0,
median => 0,
count => 0,
}],
},
'statistics calculated for the category with 10 ratings'
);
WebGUI::Cache->new($session,"matrixStatistics_".$matrix->getId)->delete;
$matrixListing->setRatings({category2=>'5'});
$matrix->view;
my $varStatisticsEncoded = WebGUI::Cache->new($session,"matrixStatistics_".$matrix->getId)->get;
my $varStatistics = JSON->new->decode($varStatisticsEncoded);
cmp_deeply(
{
best_rating_loop => $varStatistics->{best_rating_loop},
worst_rating_loop => $varStatistics->{worst_rating_loop},
},
{
best_rating_loop => [{
url => '/'.$matrixListing->get('url'),
category=> 'category1',
name => 'untitled',
mean => 2,
median => 3,
count => 10,
},
{
url => '/'.$matrixListing->get('url'),
category=> 'category2',
name => 'untitled',
mean => 7,
median => 9,
count => 10,
}],
worst_rating_loop => [{
url => '/'.$matrixListing->get('url'),
category=> 'category1',
name => 'untitled',
mean => 2,
median => 3,
count => 10,
},
{
url => '/'.$matrixListing->get('url'),
category=> 'category2',
name => 'untitled',
mean => 7,
median => 9,
count => 10,
}],
},
'statistics calculated for the category with 10 ratings'
);