PHP fake average rating generator - php

Let's imagine that the material has a rating of 2.7 with 7 votes.
I want to create a script that would generate my desired rating that would look real and not fake.
For example, I want the rating to change from 2.7 to 4.6, but the number of votes should also change proportionally.
I can't figure out how to implement it correctly.
My script will make the rating 6.0 as I want, but as a result the number of votes will be as high as 500+. I want to refine the script so that it is more realistic and changes the rating with minimal votes
My code:
My script will make the rating 6.0 as I want for example, but the number of votes will be as high as 500+. I want to generate the average values of the rating based on the previous values, while the deviation in the votes should not look fake.
<?php
class RatingFaker
{
private $totalRating = 10; // Maximum rating threshold (5 or 10)
private $maxRatingGenerate = 10; // We generate maximum rating values during the passage
private $minRatingGenerarate = 5; // Minimally generates a rating value during a pass
private $minRatingCheck = 3.5; // The minimum acceptable threshold from which we start to act
public function __construct($minRatingCheck)
{
$this->minRatingCheck = $minRatingCheck;
}
private function calcAverageRating($ratings = [])
{
$totalWeight = 0;
$totalReviews = 0;
foreach ($ratings as $weight => $numberofReviews) {
$WeightMultipliedByNumber = $weight * $numberofReviews;
$totalWeight += $WeightMultipliedByNumber;
$totalReviews += $numberofReviews;
}
//divide the total weight by total number of reviews
$averageRating = $totalWeight / $totalReviews;
return [
'rating' => $averageRating,
'vote_num' => $totalReviews
];
}
private function getRandVoters()
{
$randRating = rand($this->minRatingGenerarate, $this->maxRatingGenerate);
$randVoters = rand(1, 99);
return [
$randRating => $randVoters
];
}
private function ratingLoop($valueList)
{
$valueList = array_merge($valueList, $this->getRandVoters());
$newRating = $this->calcAverageRating($valueList);
if($newRating['rating'] < $this->minRatingCheck) {
$valueList = array_merge($valueList, $this->getRandVoters());
return $this->ratingLoop($valueList);
}
if($newRating['rating'] > 10) {
$newRating['rating'] = 10;
}
return [
'rating' => round($newRating['rating'], 1),
'sum' => round($newRating['vote_num'] * round($newRating['rating'], 1)),
'voters' => $newRating['vote_num']
];
}
public function check($currentRate, $currentVoteNum)
{
if($currentRate < $this->minRatingCheck) {
$rating = $this->ratingLoop([
$currentRate => $currentVoteNum,
]);
}
return $rating ?? [];
}
}
$currentRate = 2.4;
$voteNum = 88;
$oldRating = [
'rating' => $currentRate,
'sum' => round($voteNum * $currentRate),
'voters' => $voteNum
];
$rating = [];
$ratingFaker = new RatingFaker(6.0);
$rating = $ratingFaker->check($currentRate, $voteNum);
echo '<pre>';
echo 'Was:';
print_r($oldRating);
echo "<br>";
echo "<br>";
echo "<br>";
echo 'Now:';
print_r($rating);
echo '</pre>';

When the current rating is 2.5 based on 9 votes, and you want to get a rating of 6.0 with a minimal number of votes, you need to make sure the total value of 10 votes is 60 ( 60/10 = 6.0 ).
The current rating is : ( 2.5*9 / 9 ) = 2.5
With you extra vote it is: ( (2.5*9+x) / 10 ) = 6.0
Now you only have to find the correct value for x, which is 37.5

Related

Woocommerce - Implementation of query args in the reviews counting graph only for the currently selected language

I have a code that displays reviews graph of the entire website and divides them into sections according to ratings. The problem is that this code calculates the total reviews of the whole website. I would need to filter the total reviews count according to the currently chosen language. I use WPML. Any advice?
Code:
function display_all_product_review_histogram($minimum_rating, $maximum_rating){
$all_product_review_average_rating = get_all_product_review_average_rating($minimum_rating, $maximum_rating);
$total_ratings = $all_product_review_average_rating[0]["total_ratings"];
$get_all_product_review_counts_by_ratings = get_all_product_review_counts_by_ratings($minimum_rating, $maximum_rating);
if($get_all_product_review_counts_by_ratings){
$output = '';
$sum = 0;
$total = 0;
$raw_percentages_array = array();
$percentages_array = array();
//When working with rounded percentages, we must make sure the total percentages add up to 100%.
//Creating array of rating values and its percentage
foreach ($get_all_product_review_counts_by_ratings as $key => $rating) {
$percentage = round($rating["amount"] / $total_ratings, 2) * 100;
$raw_percentages_array[] = array("value" => $rating["value"], "percent_of_total" => $percentage, 'amount'=> $rating["amount"]);
}
//Counting the total of our percents
foreach($raw_percentages_array as $key => $percent) {
$total += $percent[ "percent_of_total" ];
}
//Creating an array that will have the actual percentages after the rounding has been applied to it.
//This will help to see if we have 100% or we are not aligned
foreach($raw_percentages_array as $key => $percent){
$percentages_array[$percent["value"]] = round(($percent["percent_of_total"]/$total) * 100, 0);
}
$sum = array_sum($percentages_array); //Again counting the total of our new percents to see if it adds up to 100%
if($sum != 100){ //If we do not have 100%, then we will alter the highest percentage value so that we get a total of 100%
$highest_percentage_key = array_keys($percentages_array, max($percentages_array)); //Getting key of the highest percentage value
$percentages_array[$highest_percentage_key[0]] = 100 - ($sum - max($percentages_array)); //Alterning the percentage
}
//Now we are ready to create the output that will give us 100% in total
$r_count = 0;
$output .= "<div class='product-review-histogram'>";
foreach ($percentages_array as $key => $percentage) {
$output .= "<div class='histogram-row star-rating-". $key ."'>";
$output .= "<div class='histogram-col-1'>". $key ." star</div>";
$output .= "<div class='histogram-col-2'><div class='histogram-meter-bar'><div class='histogram-bar-temperature' style='width: ". $percentage ."%'></div></div></div>";
$output .= "<div class='histogram-col-3'>". $raw_percentages_array[$r_count]['amount'] ."</div>";
$output .= "</div>";
$r_count++;
}
$output .= "</div>";
return $output;
}else{
return;
}
}
UPDATE - sharing code of get_all_product_review_average_rating function:
function get_all_product_review_average_rating($minimum_rating, $maximum_rating){
$get_all_product_review_counts_by_ratings = get_all_product_review_counts_by_ratings($minimum_rating, $maximum_rating);
if($get_all_product_review_counts_by_ratings){ //If we have reviews
$average_rating_results = array();
$total_ratings = 0;
$total_rating_value = 0;
foreach ($get_all_product_review_counts_by_ratings as $key => $rating) {
$total_ratings = $total_ratings + $rating["amount"];
$current_rating_value = $rating["amount"] * $rating["value"];
$total_rating_value = $total_rating_value + $current_rating_value;
}
$average_rating = number_format($total_rating_value / $total_ratings, 1); //Rounding value to one decimal place
$average_rating_results[] = array(
"total_ratings" => $total_ratings,
"average_rating" => $average_rating
);
return $average_rating_results;
}else{
return;
}
}
UPDATE2 - sharing more of the functions related to the graph
function get_all_product_review_ratings(){
global $wpdb;
if ( false === ( $review_ratings = get_transient( 'all_product_review_ratings' ))){ //Checking if we have previously cached query results in order to save resources and increase speed
$review_ratings = $wpdb->get_results("
SELECT meta_value
FROM {$wpdb->prefix}commentmeta as commentmeta
JOIN {$wpdb->prefix}comments as comments ON comments.comment_id = commentmeta.comment_id
WHERE commentmeta.meta_key = 'rating' AND comments.comment_approved = 1
ORDER BY commentmeta.meta_value
", ARRAY_A);
$expiration = 60 * 5; //Expiring query results after 5 minutes
set_transient( 'all_product_review_ratings', $review_ratings, $expiration ); //Temporarily storing cached data in the database by giving it a custom name and a timeframe after which it will expire and be deleted
return $review_ratings;
}else{
return $review_ratings;
}
}
WHAT DO WE NEED TO CHANGE TO GET THIS IS PROBABLY THIS PART OF THE CODE:
$review_ratings = $wpdb->get_results("
SELECT meta_value
FROM {$wpdb->prefix}commentmeta as commentmeta
JOIN {$wpdb->prefix}comments as comments ON comments.comment_id = commentmeta.comment_id
WHERE commentmeta.meta_key = 'rating' AND comments.comment_approved = 1
ORDER BY commentmeta.meta_value
", ARRAY_A);
UPDATE 3:
function get_all_product_review_counts_by_ratings($minimum_rating, $maximum_rating){
$all_product_review_ratings = get_all_product_review_ratings();
if($all_product_review_ratings){ //If we have reviews
$all_product_review_ratings_one_dimensional_array = array_map("current", $all_product_review_ratings); //Converting two dimensional array to one dimensional array
$rating_counts = array_count_values($all_product_review_ratings_one_dimensional_array); //Creating array that consists of rating counts
$ratings = array();
while($maximum_rating >= $minimum_rating){
if(array_key_exists($maximum_rating, $rating_counts)){
$star_count = $rating_counts[$maximum_rating];
}else{
$star_count = 0;
}
//Creating array that contains information about
$ratings[] = array(
"value" => $maximum_rating,
"amount" => $star_count
);
$maximum_rating--;
}
return $ratings;
}else{
return;
}
}
function get_all_product_review_ratings() {
global $wpdb;
if (false === ( $review_ratings = get_transient('all_product_review_ratings'))) { //Checking if we have previously cached query results in order to save resources and increase speed
$review_ratings = array();
$args = array(
'status' => 'approve',
'type' => 'review',
'paged' => 0,
'meta_query' => array(
array(
'key' => 'verified',
'value' => 1
)
));
// The Query for getting reviews - WPML respected
$comments_query = new WP_Comment_Query;
$comments = $comments_query->query($args);
foreach ($comments as $comment) {
$review_ratings[] = get_comment_meta($comment->comment_ID, 'rating', 1);
}
$expiration = 60 * 5; //Expiring query results after 5 minutes
set_transient('all_product_review_ratings', $review_ratings, $expiration); //Temporarily storing cached data in the database by giving it a custom name and a timeframe after which it will expire and be deleted
return $review_ratings;
} else {
return $review_ratings;
}
}

Filing or balancing array with dynamic generated index and values

Basically I want to balance an array.
The array I want to balance is retrieved from DB and can be unknown
Here is sample array retrieved from DB, it can vary
<?php
$arr_from_DB = array(
'1'=>NULL,
'2'=>1,
'3'=>1,
);
$node_width_from_DB = 3;
$node_depth_from_DB = 2;
?>
//Max Capacity was caclulated from $node_width_from_DB, $node_depth_from_DB AND WAS ALSO SAVED in DB , simulated below for width = 3 , depth = 2
$max_cap_of_array = 13;
//With $arr_from_DB fed to the display fxn on frontend, this is the result
//What I want to achieve, I want to transform $arr_from_DB to below ARray, All Array index with negative is seen to be dynamically generated
<?php
$formated_arr = array(
'1'=>NULL,
'2'=>1,
'3'=>1,
'-1'=>1,
'-2'=>2,
'-3'=>2,
'-4'=>2,
'-5'=>3,
'-6'=>3,
'-7'=>3,
'-8'=>-1,
'-9'=>-1,
'-10'=>-1,
);
?>
//With $formated_arr fed to the display fxn on frontend, this is the result
WHAT I TRIED SO FAR
<?php
$arr_filled = RECfillMissingDownlineArr($arr_from_DB);
var_dump($arr_filled);
function RECfillMissingDownlineArr($selectedArr, $pointer=1){
$node_width_from_DB = 3;
$node_depth_from_DB = 2;
//Max Capacity was caclulated from $node_width_from_DB, $node_depth_from_DB AND WAS ALSO SAVED in DB , simulated below for width = 3 , depth = 2
$max_cap_of_array = 13;
//var_dump($Allarr);
if($pointer>= $max_cap_of_array){
return $selectedArr;
}
$array_worked = array_count_values($selectedArr);
$array_worked3 = array_keys($selectedArr);
$array_worked2 = array_values($array_worked3);
//$key_p = $array_worked3[$pointer];
foreach($array_worked as $key=>$value){
//echo 'Value nm'.$value.'<br>';
if($value<$node_width_from_DB){
$key_p = $key;
break;
}
}
$array_worked1 = array_keys($selectedArr, $key_p);
for ($i=0; $i <$width ; $i++) {
if(empty($array_worked1[$i])){
$key_pointer = $pointer * -1;
$selectedArr[$key_pointer] = $key;
$pointer++;
return RECfillMissingDownlineArr($selectedArr,$pointer);
}
}
}
OUTPUT NULL, It's not what I want, it's returning null alltogether
?>

How to avoid query inside loop in laravel

I have created a simple profit and loss calculation based on FIFO entry in my database of buy and sell order,
and get the buy orders first then I see the sell orders against them and i get the price difference between them and that my profit but now the problem is I have to get the fresh sell orders for every loop of buy order and my code get stuck when the data is large.
can anyone give me the solution for this?
Code:
//get all buy tx orders
$pnl_logs = BuyOrder::where('status', 0)->OrderBy('created_at', 'asc')->get()->take(50);
if ($pnl_logs->isEmpty())
return Response::json(['code' => 0, 'message' => 'No Record found in buy Order to update']);
foreach ($pnl_logs as $logs) {
//get current buy rate and sell rate from price automation table
$system_buy_rate = PriceAutomation::where('type', 0)->orderBy('updated_at', 'desc')->first();
$system_sell_rate = PriceAutomation::where('type', 1)->orderBy('updated_at', 'desc')->first();
//subtract percentage fees from buy orders
$sell_rate = $this->updateSellRate($logs->vendor_id, $logs->sell_rate, $system_buy_rate->base_rate);
//get all sell tx orders
$sell_orders = SellOrders::where('status', 0)->OrderBy('created_at', 'asc')->get()->take(50);
if ($sell_orders->isEmpty())
return Response::json(['code' => 0, 'message' => 'No Record found in Sell Order to update']);
$sum = 0;
$data = [];
foreach ($sell_orders as $key => $orders) {
$sum += $orders->remaining_amount;
$data[$key]['id'] = $orders->id;
$data[$key]['remaining_amount'] = $orders->remaining_amount;
$data[$key]['sell_rate'] = $orders->sell_rate * $orders->remaining_amount;
$data[$key]['system_sell_rate'] = $system_sell_rate->base_rate * $orders->remaining_amount;
$data[$key]['source'] = $orders->gold_source;
if ($sum >= $logs->gold_amount) {
$status = 0;
$rm_balance = 0;
$avg = 0;
$system_avg = 0;
$buy_rm_amount = $logs->gold_amount;
foreach ($data as $k => $v) {
$buy_rm_amount -= $v['remaining_amount'];
if ($buy_rm_amount > 0) {
//a sell tx order is completely consumed for buy tx order
$avg += $v['sell_rate'];
$system_avg += $v['system_sell_rate'];
$status = 1;
} else {
//if buy order is completely satisfied sell tx order
$rm_balance = $sum - $logs->gold_amount;
$avg += ($v['remaining_amount'] - $rm_balance) * $orders->sell_rate;
$system_avg += ($v['remaining_amount'] - $rm_balance) * $system_sell_rate->base_rate;
if ($rm_balance == 0) {
$status = 1;
} else {
$status = 0;
}
}
//update sell order status
SellOrders::where('id', $v['id'])->update(['status' => $status, 'remaining_amount' => $rm_balance, 'system_sell_rate' => $system_sell_rate->base_rate]);
//entry in pnl log
$pnlLogData = [
'tx_id' => $logs->tx_id,
'buy_order_amount' => $logs->gold_amount,
'sell_order_amount' => $v['remaining_amount'] - $rm_balance,
'gold_source' => $v['source']
];
PnlLog::create($pnlLogData);
}
$logs->system_sell_rate = ($logs->system_sell_rate == 0) ? $sell_rate['system_rate'] : $logs->system_sell_rate;
$logs->system_buy_rate = $system_avg;
$logs->buy_rate = $avg;
$logs->sell_rate = $sell_rate['rate'];
$logs->status = 1;
$logs->save();
break;
}

Weighted Load Balancing Algorithm into PHP Application

I want to resolve weighted an Adapter from an factory which could be configured by user (enable/disable and weight %).
Example:
AdapterW ≃ 20% of transaction
AdapterX ≃ 30% of transaction
AdapterY ≃ 40% of transaction
AdapterZ ≃ 10% of transaction
I can grant that all items will never sum more than one hundred (100%), but sometimes any adapter could be deactivated.
I have the following parameters:
public function handleAdapter()
{
$isWActive = (boolean)$this->_config[self::W];
$isXActive = (boolean)$this->_config[self::X];
$isYActive = (boolean)$this->_config[self::Y];
$isZActive = (boolean)$this->_config[self::Z];
$WPercentage = (int)$this->_config[self::LOAD_BALANCE_W];
$XPercentage = (int)$this->_config[self::LOAD_BALANCE_X];
$YPercentage = (int)$this->_config[self::LOAD_BALANCE_Y];
$ZPercentage = (int)$this->_config[self::LOAD_BALANCE_Z];
.
.
.
return (self::W | self::X | self::Y | self::Z);
}
How can i balance weighted between this adapters dynamically?
Edit
created a gist to a executable code: https://gist.github.com/markomafs/5d892d06d6670909f9b4
This may not be the best approach, but you can try something like this:
public function handleAdapter()
{
//an array to return the balanced entries
$balancedEntries[] = false;
//verifies which of the options are active
$isWActive = (boolean)$this->_config[self::W];
$isXActive = (boolean)$this->_config[self::X];
$isYActive = (boolean)$this->_config[self::Y];
$isZActive = (boolean)$this->_config[self::Z];
//get configured percentage of each
$WPercentage = (int)$this->_config[self::LOAD_BALANCE_W];
$XPercentage = (int)$this->_config[self::LOAD_BALANCE_X];
$YPercentage = (int)$this->_config[self::LOAD_BALANCE_Y];
$ZPercentage = (int)$this->_config[self::LOAD_BALANCE_Z];
//here you fill the array according to the proportion defined by the percentages
if ($isWActive) {
for ($i = 0; $i < $WPercentage; $i++) {
$balancedEntries[] = self::W;
}
}
if ($isXActive) {
for ($i = 0; $i < $XPercentage; $i++) {
$balancedEntries[] = self::X;
}
}
if ($isYActive) {
for ($i = 0; $i < $YPercentage; $i++) {
$balancedEntries[] = self::Y;
}
}
if ($isZActive) {
for ($i = 0; $i < $ZPercentage; $i++) {
$balancedEntries[] = self::Z;
}
}
return $balancedEntries;
}
And then, in case you want a proportion of 1 to 100 (as in percentages):
$balancedResult = $balancedEntries[array_rand($balancedEntries, 1)];
Since array_rand will return 1 key from the original array, you use it to get it's value.
Another try, this should work for your case - But it only work if you have an adapter as a single char string, this is not visible by your question.
public function handleAdapter()
{
# a map with all adapters
$map = array(
self::W => self::LOAD_BALANCE_W,
self::X => self::LOAD_BALANCE_X,
self::Y => self::LOAD_BALANCE_Y,
self::Z => self::LOAD_BALANCE_Z
);
# generate a string map with one char per percentage point
$stringMap = "";
foreach($map as $key => $value){
# skip if disabled
if(!$this->_config[$key]) continue;
# repeat the key for each percentage point
$stringMap .= str_repeat($key, (int)$this->_config[$value]);
}
# return a random string char from the map
return $stringMap[rand(0, strlen($stringMap) - 1)];
}
Edit: I've misunderstood the question, the answer is wrong.
I understand your question so that you always want to return the adapter with the lowest load to force traffic to this adapter.
public function handleAdapter()
{
$isWActive = (boolean)$this->_config[self::W];
$isXActive = (boolean)$this->_config[self::X];
$isYActive = (boolean)$this->_config[self::Y];
$isZActive = (boolean)$this->_config[self::Z];
$WPercentage = (int)$this->_config[self::LOAD_BALANCE_W];
$XPercentage = (int)$this->_config[self::LOAD_BALANCE_X];
$YPercentage = (int)$this->_config[self::LOAD_BALANCE_Y];
$ZPercentage = (int)$this->_config[self::LOAD_BALANCE_Z];
$map = array();
if($isWActive) $map[self::W] = $WPercentage;
if($isXActive) $map[self::X] = $XPercentage;
if($isYActive) $map[self::Y] = $YPercentage;
if($isZActive) $map[self::Z] = $ZPercentage;
asort($map);
return key($map);
}
Edit: Fixed wrong sort(), you need asort() to maintain the index.

Elasticsearch scroll api search "from"

I have a script that generates sitemaps based on url index http://example.com/sitemap.index.xml where index is a number >0 that defines what results should be included in each chunk.
$chunk = 10000;
$counter = 0;
$scroll = $es->search(array(
"index" => "index",
"type" => "type",
"scroll" => "1m",
"search_type" => "scan",
"size" => 10,
"from" => $chunk * ($index - 1)
));
$sid = $scroll['_scroll_id'];
while($counter < $chunk){
$docs = $es->scroll(array(
"scroll_id" => $sid,
"scroll" => "1m"
));
$sid = $docs['_scroll_id'];
$counter += count($docs['hits']['hits']);
}
// ...
Now each time I access http://example.com/sitemap.1.xml or http://example.com/sitemap.2.xml the results returned from ES are exactly the same. It returns 50 results (10 per each shard) but does not seem to take count of from = 0, from = 10000.
I'm using elasticsearch-php as ES library.
Any ideas?
In Java, it can be done as follows
QueryBuilder query = QueryBuilders.matchAllQuery();
SearchResponse scrollResp = Constants.client.prepareSearch(index)
.setTypes(type).setSearchType(SearchType.SCAN)
.setScroll(new TimeValue(600000)).setQuery(query)
.setSize(500).execute().actionGet();
while (true) {
scrollResp = Constants.client
.prepareSearchScroll(scrollResp.getScrollId())
.setScroll(new TimeValue(600000)).execute().actionGet();
System.out.println("Record count :"
+ scrollResp.getHits().getHits().length);
total = total + scrollResp.getHits().getHits().length;
System.out.println("Total record count: " + total);
for (SearchHit hit : scrollResp.getHits()) {
//handle the hit
}
// Break condition: No hits are returned
if (scrollResp.getHits().getHits().length == 0) {
System.out.println("All records are fetched");
break;
}
}
Hope it helps.

Categories