Refine article ranking based on views of all articles

Asked

Viewed 91 times

3

The idea is to ascertain the reputation of a particular article based on the views of all existing articles.

An article can have a reputation of 1 to 5 stars, the same being constantly changing based on the views recorded for all articles.

The goal is to assign more stars to the most viewed article, knowing that the assigned stars are calculated in real time by viewing recorded so far in all catalog articles.

Mysql

For this purpose, whenever an article is viewed, the display is recorded in a table:

DESCRIBE `product__statistic_views` 
┌───────────────┬───────────┬──────┬─────┬─────────────────────┬────────────────┐
│ Field         │ Type      │ Null │ Key │ Default             │ Extra          │
├───────────────┼───────────┼──────┼─────┼─────────────────────┼────────────────┤
│ id            │ int(13)   │ NO   │ PRI │ NULL                │ auto_increment │
├───────────────┼───────────┼──────┼─────┼─────────────────────┼────────────────┤
│ product_id    │ int(13)   │ NO   │ MUL │ 0                   │                │
├───────────────┼───────────┼──────┼─────┼─────────────────────┼────────────────┤
│ session_id    │ char(100) │ NO   │ MUL │ old-na              │                │
├───────────────┼───────────┼──────┼─────┼─────────────────────┼────────────────┤
│ page_views    │ int(13)   │ NO   │ 0   │                     │                │
├───────────────┼───────────┼──────┼─────┼─────────────────────┼────────────────┤
│ date_created  │ datetime  │ NO   │ MUL │ 0000-00-00 00:00:00 │                │
└───────────────┴───────────┴──────┴─────┴─────────────────────┴────────────────┘

Example of a record:

┌────┬────────────┬──────────────────────────────────┬────────────┬─────────────────────┐
│ id │ product_id │ session_id                       │ page_views │ date_created        │
├────┼────────────┼──────────────────────────────────┼────────────┼─────────────────────┤
│ 2  │ 37         │ 153dd95d83bc6a6691a4c3bab42215c9 │ 3          │ 2014-12-02 18:47:17 │
└────┴────────────┴──────────────────────────────────┴────────────┴─────────────────────┘

This tells us that Article #37 has a unique visitor, who even viewed the product 3 times in the same session.

PHP

On the PHP side, the information is processed as follows:

/**
 * Product Rating
 *
 * Prepare the necessary HTML to present the product
 * rating stats based on their views count while
 * compared to all products views.
 * 
 * @param integer $count Product views count.
 * @param integer $grandTotal Sum of all products views.
 *
 * @return string $returnHtml HTML ready to be used.
 */
public function productRating($count=0, $grandTotal=0) {

    $returnHtml = '
    <span class="fa fa-star-o"></span>
    <span class="fa fa-star-o"></span>
    <span class="fa fa-star-o"></span>
    <span class="fa fa-star-o"></span>
    <span class="fa fa-star-o"></span>';

    if (intval($count)>=1) {

        $rating = number_format( ceil( ( ($count*100) / $grandTotal ) / 20 ), 0);

        if ($rating>0) {

            $returnHtml = '';

            for ($i=0; $i<$rating; $i++) {
                $returnHtml.= '<span class="fa fa-star" data-rating="'.$rating.'"></span>';
            }

            for ($i=5; $i>$rating; $i--) {
                $returnHtml.= '<span class="fa fa-star-o" data-rating="'.$rating.'"></span>';
            }
        }
    }

    return $returnHtml;
}

Example of use:

/* Visualizações são únicas, pelo que o total de visualizações do produto é uma
 * contagem dos registos com o seu ID na tabela em cima, e o total de visualizações
 * de todos os produtos é uma contagem de todos os registos na tabela em cima referida.
 */
$ratingHtml = $this->productRating(1, 10);

HTML

The result will be something like this:

Ilustração das estrelas que denotam a classificação do produto


Question

For what has been described, the function that deals with determining the classification of each product is performing its work efficiently?

This whole process could be simplified?

  • Explain to me the following: Does that article that has a majority of views on everyone else get 5 stars? Or is it a question of percentage? those who have the highest percentage of views in relation to the total receive 5 stars... I did not understand the division by 20 there in the code

  • @touchmx Roughly, each star is equal to 20%. If the product is 80% up, it takes 5 Stars. Note that the code may be 100% wrong, hence this question asking review of it.

2 answers

2

If I understand the code correctly, this method should generate a very low value for each product, since none will have 100% of the views you pass in $grandTotal. An alternative way to calculate would be to compare with the product that has more views, instead of comparing with the sum of all the views. In SQL, this could be done like this:

SELECT
  product_id,
  page_views,
  CEIL((page_views / (SELECT MAX(page_views) FROM product__statistic_views)) * 100) AS percentual
FROM product__statistic_views
-- WHERE product_id = ? /* para filtrar por produto se necessário */

http://sqlfiddle.com/#! 2/93913/4

This method would still have the problem of generating low values for all new products, which usually tend to have few views. You could use some reference date to minimize this. For example, to compare a product with those registered up to 7 days before it (considering that date_created is the date of registration):

SELECT
  product_id,
  page_views,
  CEIL((page_views / (SELECT MAX(page_views) FROM product__statistic_views WHERE date_created BETWEEN DATE_SUB(date_created, INTERVAL 7 DAY) AND date_created)) * 100) AS percentual
FROM product__statistic_views
-- WHERE product_id = ? /* para filtrar por produto se necessário */

0

The calculation is perfect, what I think is wrong is the fact that the variable $returnHtml is started with stars. In this case, it seems to me that more than 5 stars will be shown. So I believe the correct is the following:

/**
 * Product Rating
 *
 * Prepare the necessary HTML to present the product
 * rating stats based on their views count while
 * compared to all products views.
 * 
 * @param integer $count Product views count.
 * @param integer $grandTotal Sum of all products views.
 *
 * @return string $returnHtml HTML ready to be used.
 */
public function productRating($count=0, $grandTotal=0) {

    $returnHtml = '';

    if (intval($count)>=1) {

        $rating = number_format( ceil( ( ($count*100) / $grandTotal ) / 20 ), 0);

            for ($i=1; $i<=5; $i++) {
                if($i <= $rating){
                   $returnHtml .= '<span class="fa fa-star" data-rating="'.$i.'"></span>';
                }else{
                   $returnHtml .= '<span class="fa fa-star-o" data-rating="'.$i.'"></span>';
                }
            }    

        }else{
           $returnHtml = '
           <span class="fa fa-star-o"></span>
           <span class="fa fa-star-o"></span>
           <span class="fa fa-star-o"></span>
           <span class="fa fa-star-o"></span>
           <span class="fa fa-star-o"></span>';

        }

    return $returnHtml;
}

I’m assuming that the fa-star class is the disabled star, the gray that you showed in the example.

  • You have assumed correctly in relation to colors! But, the variable $returnHtml has stars deactivated because if the parameter $count is 0 (zero), the idea is to have stars, although empty. According to your suggestion, if $count===0 we will run out of stars in the product because it is only the first control if (intval($count)>=1) {...}.

  • I get it, I’ll edit it. the change is simple.

  • Now you’re right, take a test and give me a feedback.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.