权重逻辑实现

时间:2018-07-19 12:52:21

标签: php math logic

假设我有4个广告横幅:

  • 横幅A-价格10 $
  • 横幅B-价格5 $
  • 横幅C-价格3 $
  • 横幅D-价格1 $

现在的要求是根据重量显示广告。例如横幅A与横幅B相比会出现更多时间。横幅B与横幅C相比会出现更多时间,依此类推。

广告横幅可以显示多少次或横幅可以显示多长时间没有限制。每当用户刷新屏幕时,他们都会获得一个横幅,但基于上述重量。

现在,我不确定为此需要哪种逻辑或数学公式。我想在PHP中建立该逻辑,因此添加了php标签。

我认为我将拥有一个横幅表,基于此,我们将基于“加权”逻辑生成一个队列,并将一一发送横幅。

2 个答案:

答案 0 :(得分:1)

这里是一个例子,剩下的我会留给你:

  • $ads是您的广告数组(id和权重),可以从有效广告数据库中选择。
  • show_ad是一种算法,它将所有广告合并到权重中,然后选择一个随机数,然后减去直到达到最接近的权重,随着时间的流逝,这是随机移位的。
  • simulate_views刚刚运行了100多个视图,以向您显示它的权重。

获得随机ID后,您将使用该ID来获取广告内容。

<?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));

某些结果(100次迭代):

Array
(
    [30] => 56
    [10] => 14
    [20] => 30
)

Array
(
    [20] => 35
    [30] => 51
    [10] => 14
)

Array
(
    [20] => 32
    [30] => 57
    [10] => 11
)

https://3v4l.org/1Giuc

注意:请确保在> = PHP7.1上运行,否则请使用mt_rand。

答案 1 :(得分:0)

感谢@Rakesha Shastri和@Lawrence Cherone,我能够弄清楚。

我所做的是创建2个表。

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

之后,在ad_banner表中添加了一些条目。

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();
}

然后简单地调用actionFetchbanner函数。