feature 2384: improve average rating calculation (still need to update language files)
git-svn-id: http://piwigo.org/svn/trunk@11827 68402e56-0260-453c-a942-63ccdbb3a9ee
This commit is contained in:
parent
86bc4d1143
commit
4e4dc79e51
13 changed files with 115 additions and 101 deletions
|
|
@ -109,7 +109,7 @@ $sort_fields = array(
|
|||
'file' => l10n('File name'),
|
||||
'date_creation' => l10n('Creation date'),
|
||||
'date_available' => l10n('Post date'),
|
||||
'average_rate' => l10n('Average rate'),
|
||||
'average_rate' => l10n('Rating score'),
|
||||
'hit' => l10n('Most visited'),
|
||||
'id' => 'Id',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -273,7 +273,7 @@ $sort_fields = array(
|
|||
'' => '',
|
||||
'date_creation' => l10n('Creation date'),
|
||||
'date_available' => l10n('Post date'),
|
||||
'average_rate' => l10n('Average rate'),
|
||||
'average_rate' => l10n('Rate score'),
|
||||
'hit' => l10n('Most visited'),
|
||||
'file' => l10n('File name'),
|
||||
'id' => 'Id',
|
||||
|
|
|
|||
|
|
@ -1050,67 +1050,6 @@ UPDATE '.IMAGES_TABLE.'
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* update images.average_rate field
|
||||
* param int $element_id optional, otherwise applies to all
|
||||
* @return void
|
||||
*/
|
||||
function update_average_rate( $element_id=-1 )
|
||||
{
|
||||
$query = '
|
||||
SELECT element_id,
|
||||
ROUND(AVG(rate),2) AS average_rate
|
||||
FROM '.RATE_TABLE;
|
||||
if ( $element_id != -1 )
|
||||
{
|
||||
$query .= ' WHERE element_id=' . $element_id;
|
||||
}
|
||||
$query .= ' GROUP BY element_id;';
|
||||
|
||||
$result = pwg_query($query);
|
||||
|
||||
$datas = array();
|
||||
|
||||
while ($row = pwg_db_fetch_assoc($result))
|
||||
{
|
||||
array_push(
|
||||
$datas,
|
||||
array(
|
||||
'id' => $row['element_id'],
|
||||
'average_rate' => $row['average_rate']
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
mass_updates(
|
||||
IMAGES_TABLE,
|
||||
array(
|
||||
'primary' => array('id'),
|
||||
'update' => array('average_rate')
|
||||
),
|
||||
$datas
|
||||
);
|
||||
|
||||
$query='
|
||||
SELECT id FROM '.IMAGES_TABLE .'
|
||||
LEFT JOIN '.RATE_TABLE.' ON id=element_id
|
||||
WHERE element_id IS NULL AND average_rate IS NOT NULL';
|
||||
if ( $element_id != -1 )
|
||||
{
|
||||
$query .= ' AND id=' . $element_id;
|
||||
}
|
||||
$to_update = array_from_query( $query, 'id');
|
||||
|
||||
if ( !empty($to_update) )
|
||||
{
|
||||
$query='
|
||||
UPDATE '.IMAGES_TABLE .'
|
||||
SET average_rate=NULL
|
||||
WHERE id IN (' . implode(',',$to_update) . ')';
|
||||
pwg_query($query);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* change the parent category of the given categories. The categories are
|
||||
* supposed virtual.
|
||||
|
|
|
|||
|
|
@ -58,7 +58,8 @@ switch ($action)
|
|||
case 'images' :
|
||||
{
|
||||
update_path();
|
||||
update_average_rate();
|
||||
include_once(PHPWG_ROOT_PATH.'include/functions_rate.inc.php');
|
||||
update_rating_score();
|
||||
break;
|
||||
}
|
||||
case 'delete_orphan_tags' :
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ AND user_id=' . $vars['u'] . '
|
|||
AND anonymous_id=\'' . $vars['a'] . '\'
|
||||
;';
|
||||
pwg_query($query);
|
||||
update_average_rate( $vars['e'] );
|
||||
update_rating_score( $vars['e'] );
|
||||
}
|
||||
|
||||
$users = array();
|
||||
|
|
@ -100,10 +100,9 @@ while ($row = pwg_db_fetch_assoc($result))
|
|||
}
|
||||
|
||||
|
||||
$query = 'SELECT COUNT(DISTINCT(i.id))
|
||||
FROM '.RATE_TABLE.' AS r, '.IMAGES_TABLE.' AS i
|
||||
WHERE r.element_id=i.id'. $page['user_filter'] .
|
||||
';';
|
||||
$query = 'SELECT COUNT(DISTINCT(r.element_id))
|
||||
FROM '.RATE_TABLE.' AS r
|
||||
WHERE 1=1'. $page['user_filter'];
|
||||
list($nb_images) = pwg_db_fetch_row(pwg_query($query));
|
||||
|
||||
|
||||
|
|
@ -131,7 +130,8 @@ $template->assign(
|
|||
|
||||
$available_order_by= array(
|
||||
array(l10n('Rate date'), 'recently_rated DESC'),
|
||||
array(l10n('Average rate'), 'average_rate DESC'),
|
||||
array(l10n('Rating score'), 'score DESC'),
|
||||
array(l10n('Average rate'), 'avg_rates DESC'),
|
||||
array(l10n('Number of rates'), 'nb_rates DESC'),
|
||||
array(l10n('Sum of rates'), 'sum_rates DESC'),
|
||||
array(l10n('File name'), 'file DESC'),
|
||||
|
|
@ -164,8 +164,9 @@ SELECT i.id,
|
|||
i.path,
|
||||
i.file,
|
||||
i.tn_ext,
|
||||
i.average_rate,
|
||||
i.average_rate AS score,
|
||||
MAX(r.date) AS recently_rated,
|
||||
ROUND(AVG(r.rate),2) AS avg_rates,
|
||||
COUNT(r.rate) AS nb_rates,
|
||||
SUM(r.rate) AS sum_rates
|
||||
FROM '.RATE_TABLE.' AS r
|
||||
|
|
@ -207,7 +208,8 @@ ORDER BY date DESC;';
|
|||
array(
|
||||
'U_THUMB' => $thumbnail_src,
|
||||
'U_URL' => $image_url,
|
||||
'AVG_RATE' => $image['average_rate'],
|
||||
'SCORE_RATE' => $image['score'],
|
||||
'AVG_RATE' => $image['avg_rates'],
|
||||
'SUM_RATE' => $image['sum_rates'],
|
||||
'NB_RATES' => (int)$image['nb_rates'],
|
||||
'NB_RATES_TOTAL' => (int)$nb_rates,
|
||||
|
|
|
|||
|
|
@ -415,7 +415,7 @@ jQuery(document).ready(function () {
|
|||
|
||||
<li>
|
||||
<label>
|
||||
<span class="property">{'Average rate'|@translate}</span>
|
||||
<span class="property">{'Rating score'|@translate}</span>
|
||||
<input type="checkbox" name="picture_informations[average_rate]" {if ($display.picture_informations.average_rate)}checked="checked"{/if}>
|
||||
</label>
|
||||
</li>
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
<tr class="throw">
|
||||
<td>{'File'|@translate}</td>
|
||||
<td>{'Number of rates'|@translate}</td>
|
||||
<td>{'Rating score'|@translate}</td>
|
||||
<td>{'Average rate'|@translate}</td>
|
||||
<td>{'Sum of rates'|@translate}</td>
|
||||
<td>{'Rate'|@translate}</td>
|
||||
|
|
@ -48,6 +49,7 @@
|
|||
<tr valign="top" class="{if $smarty.foreach.image.index is odd}row1{else}row2{/if}">
|
||||
<td rowspan="{$image.NB_RATES_TOTAL+1}"><a href="{$image.U_URL}"><img src="{$image.U_THUMB}" alt="{$image.FILE}" title="{$image.FILE}"></a></td>
|
||||
<td rowspan="{$image.NB_RATES_TOTAL+1}"><strong>{$image.NB_RATES}/{$image.NB_RATES_TOTAL}</strong></td>
|
||||
<td rowspan="{$image.NB_RATES_TOTAL+1}"><strong>{$image.SCORE_RATE}</strong></td>
|
||||
<td rowspan="{$image.NB_RATES_TOTAL+1}"><strong>{$image.AVG_RATE}</strong></td>
|
||||
<td rowspan="{$image.NB_RATES_TOTAL+1}" style="border-right: 1px solid;" ><strong>{$image.SUM_RATE}</strong></td>
|
||||
</tr>
|
||||
|
|
|
|||
|
|
@ -290,7 +290,7 @@ function get_category_preferred_image_orders()
|
|||
return trigger_event('get_category_preferred_image_orders',
|
||||
array(
|
||||
array(l10n('Default'), '', true),
|
||||
array(l10n('Average rate'), 'average_rate DESC', $conf['rate']),
|
||||
array(l10n('Rating score'), 'average_rate DESC', $conf['rate']),
|
||||
array(l10n('Most visited'), 'hit DESC', true),
|
||||
array(l10n('Creation date'), 'date_creation DESC', true),
|
||||
array(l10n('Post date'), 'date_available DESC', true),
|
||||
|
|
|
|||
|
|
@ -116,21 +116,88 @@ INSERT
|
|||
;';
|
||||
pwg_query($query);
|
||||
|
||||
// update of images.average_rate field
|
||||
return update_rating_score($image_id);
|
||||
}
|
||||
|
||||
|
||||
/* update images.average_rate field
|
||||
* we use a bayesian average (http://en.wikipedia.org/wiki/Bayesian_average) with
|
||||
C = average number of rates per item
|
||||
m = global average rate (all rates)
|
||||
|
||||
* param int $element_id optional, otherwise applies to all
|
||||
* @return array(average_rate, count) if element_id is specified
|
||||
*/
|
||||
function update_rating_score($element_id = false)
|
||||
{
|
||||
$query = '
|
||||
SELECT COUNT(rate) AS count
|
||||
, ROUND(AVG(rate),2) AS average
|
||||
SELECT element_id,
|
||||
COUNT(rate) AS rcount,
|
||||
SUM(rate) AS rsum
|
||||
FROM '.RATE_TABLE.'
|
||||
WHERE element_id = '.$image_id.'
|
||||
;';
|
||||
$row = pwg_db_fetch_assoc(pwg_query($query));
|
||||
$query = '
|
||||
UPDATE '.IMAGES_TABLE.'
|
||||
SET average_rate = '.$row['average'].'
|
||||
WHERE id = '.$image_id.'
|
||||
;';
|
||||
pwg_query($query);
|
||||
return $row;
|
||||
GROUP by element_id';
|
||||
|
||||
$all_rates_count = 0;
|
||||
$all_rates_avg = 0;
|
||||
$item_ratecount_avg = 0;
|
||||
$by_item = array();
|
||||
|
||||
$result = pwg_query($query);
|
||||
while ($row = pwg_db_fetch_assoc($result))
|
||||
{
|
||||
$all_rates_count += $row['rcount'];
|
||||
$all_rates_avg += $row['rsum'];
|
||||
$by_item[$row['element_id']] = $row;
|
||||
}
|
||||
|
||||
$all_rates_avg /= $all_rates_count;
|
||||
$item_ratecount_avg = $all_rates_count / count($by_item);
|
||||
|
||||
$updates = array();
|
||||
foreach ($by_item as $id => $rate_summary )
|
||||
{
|
||||
$score = ( $item_ratecount_avg * $all_rates_avg + $rate_summary['rsum'] ) / ($item_ratecount_avg + $rate_summary['rcount']);
|
||||
$score = round($score,2);
|
||||
if ($id==$element_id)
|
||||
{
|
||||
$return = array(
|
||||
'score' => $score,
|
||||
'average' => round($rate_summary['rsum'] / $rate_summary['rcount'], 2),
|
||||
'count' => $rate_summary['rcount'],
|
||||
);
|
||||
}
|
||||
$updates[] = array( 'id'=>$id, 'average_rate'=>$score );
|
||||
}
|
||||
mass_updates(
|
||||
IMAGES_TABLE,
|
||||
array(
|
||||
'primary' => array('id'),
|
||||
'update' => array('average_rate')
|
||||
),
|
||||
$updates
|
||||
);
|
||||
|
||||
//set to null all items with no rate
|
||||
if ( !isset($by_item[$element_id]) )
|
||||
{
|
||||
$query='
|
||||
SELECT id FROM '.IMAGES_TABLE .'
|
||||
LEFT JOIN '.RATE_TABLE.' ON id=element_id
|
||||
WHERE element_id IS NULL AND average_rate IS NOT NULL';
|
||||
|
||||
$to_update = array_from_query( $query, 'id');
|
||||
|
||||
if ( !empty($to_update) )
|
||||
{
|
||||
$query='
|
||||
UPDATE '.IMAGES_TABLE .'
|
||||
SET average_rate=NULL
|
||||
WHERE id IN (' . implode(',',$to_update) . ')';
|
||||
pwg_query($query);
|
||||
}
|
||||
}
|
||||
|
||||
return isset($return) ? $return : array('score'=>null, 'average'=>null, 'count'=>0 );
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
@ -28,7 +28,8 @@
|
|||
|
||||
if ($conf['rate'])
|
||||
{
|
||||
if ( NULL != $picture['current']['average_rate'] )
|
||||
$rate_summary = array( 'count'=>0, 'score'=>$picture['current']['average_rate'], 'average'=>null );
|
||||
if ( NULL != $rate_summary['score'] )
|
||||
{
|
||||
$query = '
|
||||
SELECT COUNT(rate) AS count
|
||||
|
|
@ -36,18 +37,14 @@ SELECT COUNT(rate) AS count
|
|||
FROM '.RATE_TABLE.'
|
||||
WHERE element_id = '.$picture['current']['id'].'
|
||||
;';
|
||||
$row = pwg_db_fetch_assoc(pwg_query($query));
|
||||
list($rate_summary['count'], $rate_summary['average']) = pwg_db_fetch_row(pwg_query($query));
|
||||
}
|
||||
else
|
||||
{ // avg rate null -> no rate -> no need to query db
|
||||
$row = array( 'count'=>0, 'average'=>NULL );
|
||||
}
|
||||
$template->assign('rate_summary', $row);
|
||||
$template->assign('rate_summary', $rate_summary);
|
||||
|
||||
$user_rate = null;
|
||||
if ($conf['rate_anonymous'] or is_autorize_status(ACCESS_CLASSIC) )
|
||||
{
|
||||
if ($row['count']>0)
|
||||
if ($rate_summary['count']>0)
|
||||
{
|
||||
$query = 'SELECT rate
|
||||
FROM '.RATE_TABLE.'
|
||||
|
|
|
|||
|
|
@ -781,14 +781,20 @@ SELECT id, name, permalink, uppercats, global_rank, commentable
|
|||
$related_tags[$i]=$tag;
|
||||
}
|
||||
//------------------------------------------------------------- related rates
|
||||
$query = '
|
||||
$rating = array('score'=>$image_row['average_rate'], 'count'=>0, 'average'=>null);
|
||||
if (isset($rating['score']))
|
||||
{
|
||||
$query = '
|
||||
SELECT COUNT(rate) AS count
|
||||
, ROUND(AVG(rate),2) AS average
|
||||
FROM '.RATE_TABLE.'
|
||||
WHERE element_id = '.$image_row['id'].'
|
||||
;';
|
||||
$rating = pwg_db_fetch_assoc(pwg_query($query));
|
||||
$rating['count'] = (int)$rating['count'];
|
||||
$row = pwg_db_fetch_assoc(pwg_query($query));
|
||||
$rating['score'] = (float)$rating['score'];
|
||||
$rating['average'] = (float)$row['average'];
|
||||
$rating['count'] = (int)$row['count'];
|
||||
}
|
||||
|
||||
//---------------------------------------------------------- related comments
|
||||
$related_comments = array();
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ function updateRating(e)
|
|||
if (gRatingOptions.ratingSummaryElement)
|
||||
{
|
||||
var t = gRatingOptions.ratingSummaryText;
|
||||
var args =[result.average, result.count], idx = 0, rexp = new RegExp( /%\.?\d*[sdf]/ );
|
||||
var args =[result.score, result.count, result.average], idx = 0, rexp = new RegExp( /%\.?\d*[sdf]/ );
|
||||
while (idx<args.length) t=t.replace(rexp, args[idx++]);
|
||||
gRatingOptions.ratingSummaryElement.innerHTML = t;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -196,11 +196,11 @@ y.callService(
|
|||
|
||||
{if $display_info.average_rate and isset($rate_summary)}
|
||||
<tr id="Average">
|
||||
<td class="label">{'Average rate'|@translate}</td>
|
||||
<td class="label">{'Rating'|@translate}</td>
|
||||
<td class="value" id="ratingSummary">
|
||||
{if $rate_summary.count}
|
||||
{assign var='rate_text' value='%.2f (rated %d times)'|@translate}
|
||||
{$pwg->sprintf($rate_text, $rate_summary.average, $rate_summary.count)}
|
||||
{$pwg->sprintf($rate_text, $rate_summary.score, $rate_summary.count, $rate_summary.average)}
|
||||
{else}
|
||||
{'no rate'|@translate}
|
||||
{/if}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue