Let's assume i have 4 advertisement banner:
Now the requirement is to display ads based on the weightage. like Banner A will appear more time compare to Banner B. Banner B will appear more time compare to Banner C and so on.
There is no limit like how many times ad banner can display or how long the banner can display. When ever user refresh the screen they will get one banner, but based on above weightage.
Now i am not sure what kind of logic or mathematical formula is required for that. I want to build that logic in PHP hence adding the php tag.
what i am think is i will have one banner table and based on that we will generate one queue based on the Weightage logic and will send banner one by one.
Thanks to @Rakesha Shastri, @Lawrence Cherone i am able to figured it out.
What i have done is created 2 tables.
CREATE TABLE `ad_banner` (
`banner_id` int(11) NOT NULL AUTO_INCREMENT,
`banner_name` varchar(255) NOT NULL,
`weightage` int(3) NOT NULL,
`price` decimal(5,2) NOT NULL,
PRIMARY KEY (`banner_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1
CREATE TABLE `ad_banner_queue` (
`ad_quque_id` int(11) NOT NULL AUTO_INCREMENT,
`banner_name` varchar(255) NOT NULL,
`is_sent` tinyint(1) NOT NULL,
PRIMARY KEY (`ad_quque_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1
After that added few entries in ad_banner table.
public function actionGeneratequeue(){
/* First check that there is existing queue, if so don't generate it */
$data_exist = Yii::app()->db->createCommand()
->select('ad_quque_id')
->from('ad_banner_queue')
->where('is_sent=0')
->queryScalar();
if($data_exist===false){
/* Fetch all banner */
$ads = Yii::app()->db->createCommand()
->select('*')
->from('ad_banner')
->queryAll();
if(!empty($ads)){
foreach($ads as $ad){
/* Make entry as per that weightage, example, if weightage is 10 then make entry 10 times */
for($i=1;$i<=$ad['weightage'];$i++){
$command = Yii::app()->db->createCommand();
$command->insert('ad_banner_queue', array(
'banner_name' => $ad['banner_name'],
));
}
}
} else{
echo "No Banner Found!";
exit;
}
} else{
echo "Queue already exist";
exit;
}
}
/* Fetch banner */
public function actionFetchbanner(){
/* Fetch the Random from table */
$ads_queue = Yii::app()->db->createCommand()
->select('*')
->from('ad_banner_queue')
->where('is_sent=0')
->order('RAND()')
->queryRow();
if($ads_queue===false){
$this->actionGeneratequeue();
}
/* Now, marked that one as is_sent */
$command = Yii::app()->db->createCommand();
$command->update('ad_banner_queue', array(
'is_sent'=>1,
), 'ad_quque_id=:ad_quque_id', array(':ad_quque_id'=>$ads_queue['ad_quque_id']));
echo "<pre>";print_r($ads_queue);echo "</pre>";exit();
}
Then simple call the actionFetchbanner
function.
Here is an example, I will leave you to build the rest:
$ads
is your array of ads (id and weight) this would be selected from the database of active ads.show_ad
is the algorithm, it combines all the ads into their weights, then picks a random number, then subtracts until it reaches the closest weight, over time this is random shifted.simulate_views
just runs over 100 views to show you that it's weighted.Upon getting a random id, you would use that to get the ad content.
<?php
// id => weight
$ads = [
10 => 5,
20 => 10,
30 => 15
];
function show_ad($ads) {
// calculate the total of all weights
$combined = array_sum($ads);
// pick a random number from $combined weights
$random = rand(0, $combined - 1);
// keep subtracting weight until we drop below an ad weight
foreach ($ads as $id => $weight) {
if ($random < $weight) return $id;
$random -= $weight;
}
return $random;
}
function simulate_views($ads, $rounds = 100) {
$result = [];
for ($i = 0; $i < $rounds; $i++) {
$id = show_ad($ads);
$result[$id] = isset($result[$id]) ? $result[$id]+1: 1;
}
return $result;
}
print_r(simulate_views($ads));
Some Results (100 iterations):
Array
(
[30] => 56
[10] => 14
[20] => 30
)
.
Array
(
[20] => 35
[30] => 51
[10] => 14
)
.
Array
(
[20] => 32
[30] => 57
[10] => 11
)
Note: be sure to run on >= PHP7.1, else use mt_rand.