将一个数分成若干份,并且以不返回的抽奖方式来产生暴击数(算法)

 将一个数分成若干份,并且以不返回的抽奖方式来产生暴击数(算法)

 简介:现象好多商城有领钻石,类似于挖矿;也就是伪区块链(实例:网易星球);我做一个项目要求是:一个用户获得一定数的钻石;将这个数随机分成60份(后台可以变),没份数要保留五位小数,这60份数中大小需要控制最大和最小数不要相差很大,并且40份中随机产生一个暴击,这要在暴击概率内,这暴击数是平均数的几倍;倍数后台可以变,暴击率后台也可以变,产生暴击数但是60份还是保持不变;(描述不是很好)PHP代码如下:

$sql="select * from wemall_block_chain_config where id=1";
$block_chain_config = $mysqli -> query($sql);
$configlist=$block_chain_config -> fetch_assoc();
//区块链凌晨数据处理
$today_time=strtotime(date("Y-m-d"));//今天凌晨时间戳
$add_time=intval($today_time)+(3*60);//今天凌晨时间戳+3分钟
$strtime=time();//当前时间
if($configlist['c_time']<$today_time) {
    //阻止一天在规定时间中重复执行
    if ($strtime >= $today_time ) {
        //确保凌晨执行程序
        $min_multiple = $configlist['min_multiple'];//暴击最小倍数
        $max_multiple = $configlist['max_multiple'];//暴击最大倍数
        $today_bear_num = $configlist['today_bear_num'];//当日平台总发放的钻石数
        $probability = $configlist['probability'] / 100;//暴击概率
        $set_bear_power = $configlist['bear_power'];//超过这个数才可以参加暴击
        $equal_division = $configlist['equal_division'];//钻石随机划分多少份
        //获取平台所有用户的总动力
        $sql = "SELECT sum(number) as just_total FROM wemall_bear_power_log WHERE ctime < '$today_time' and is_income=1";//总增加动力值
        $just_total = $mysqli->query($sql);
        $just_total = $just_total->fetch_assoc();
        $sql = "SELECT sum(number) as negative_total FROM wemall_bear_power_log WHERE ctime < '$today_time' and is_income=2";//总减少动力值
        $negative_total = $mysqli->query($sql);
        $negative_total = $negative_total->fetch_assoc();
        $total_list=$just_total['just_total']-$negative_total['negative_total'];//总增加动力值-总减少动力值(净总动力值)
        if ($total_list) {
            $total = $total_list;//平台所有用户的净总动力值(昨天以前的)
        }else{
            $total = 0;
        }
        //获得暴击人数
        if ($today_bear_num <= 25) {
            $canshu = ($today_bear_num / 2) - 1;
            $lists = getsum($canshu, $today_bear_num, $today_bear_num);
            if ($lists > $probability) {
                $result = 0;
            } else if ($lists == $probability) {
                $result = $canshu;
            } else if ($lists < $probability) {
                $result = getnum(1, 1, $today_bear_num, $today_bear_num, $probability);
            }
        } else {
            $result = getnum(1, 1, $today_bear_num, $today_bear_num, $probability);
        }
        $riot_number = $result;//暴击人数
        $sql = "SELECT id FROM wemall_user ORDER BY id asc";
        $userlist = $mysqli->query($sql);
        while ($userlists = $userlist->fetch_assoc()) {
            //获取暴击数组
            if ($userlists['id']) {
                //单个用户动力值
                $user_ids = $userlists['id'];
                $sql = "SELECT sum(number) as just_total FROM wemall_bear_power_log WHERE ctime < '$today_time' and user_id='$user_ids' and is_income=1";//个人总增加动力值
                $person_just_total = $mysqli->query($sql);
                $person_just_total = $person_just_total->fetch_assoc();
                $sql = "SELECT sum(number) as negative_total FROM wemall_bear_power_log WHERE ctime < '$today_time' and user_id='$user_ids' and is_income=2";//总减少动力值
                $person_negative_total = $mysqli->query($sql);
                $person_negative_total = $person_negative_total->fetch_assoc();
                $person_total_list=$person_just_total['just_total']-$person_negative_total['negative_total'];//总收入-总支出
                if ($person_total_list) {
                    $person_total = $person_total_list;//用户的净总动力值(昨天以前的)
                } else {
                    $person_total = 0;
                }
                if ($person_total > $set_bear_power) {
                    //生成暴击数组
                    $sql = "select violent_data,c_time from wemall_block_chain_config where id=1";
                    $violent_data = $mysqli->query($sql);
                    $violent_data = $violent_data->fetch_assoc();
                    if ($violent_data['c_time'] < $strtime) {
                        //老的数据
                        $arrlist['attack'] = mt_rand($min_multiple, $max_multiple);
                        $arrlist['v'] = $person_total;
                        $arrlist['user_id'] = $user_ids;
                        $arr[] = $arrlist;
                        $arr = json_encode($arr);
                        $sql = "UPDATE wemall_block_chain_config SET violent_data='$arr',c_time='$strtime' WHERE id=1";
                        $update_data = $mysqli->query($sql);
                        if (!$update_data) {
                            $mysqli->rollback();
                            $result = false;
                            exit;
                        }
                    } else {
                        //新数据
                        if ($violent_data['violent_data']) {
                            //有数据的
                            $arrlist['attack'] = mt_rand($min_multiple, $max_multiple);
                            $arrlist['v'] = $person_total;
                            $arrlist['user_id'] = $user_ids;
                            $arralist = json_decode($violent_data['violent_data'], true);
                            $arralist[] = $arrlist;
                            $arr = json_encode($arralist);
                            $sql = "UPDATE wemall_block_chain_config SET violent_data='$arr',c_time='$strtime' WHERE id=1";
                            $update_data = $mysqli->query($sql);
                            if (!$update_data) {
                                $mysqli->rollback();
                                $result = false;
                                exit;
                            }
                        } else {
                            //没有数据
                            $arrlist['attack'] = mt_rand($min_multiple, $max_multiple);
                            $arrlist['v'] = $person_total;
                            $arrlist['user_id'] = $user_ids;
                            $arr[] = $arrlist;
                            $arr = json_encode($arr);
                            $sql = "UPDATE wemall_block_chain_config SET violent_data='$arr',c_time='$strtime' WHERE id=1";
                            $update_data = $mysqli->query($sql);
                            if (!$update_data) {
                                $mysqli->rollback();
                                $result = false;
                                exit;
                            }
                        }
                    }
                }
            }
        }
        //获取暴击人的user_id,暴击倍数。数组
        $sql = "select violent_data,c_time from wemall_block_chain_config where id=1";
        $violent_datas = $mysqli->query($sql);
        $violent_datas = $violent_datas->fetch_assoc();
        $prize_arr = json_decode($violent_datas['violent_data'], true);
        $attack_list = array();
        for ($i = 0; $i < $riot_number; $i++) {
            if ($violent_datas['c_time'] <= $strtime) {
                $list_data = get_violent_attack($prize_arr);
                if ($list_data['no']) {
                    $prize_arr = $list_data['no'];
                }
                if ($list_data['yes']) {
                    $attack_list[] = $list_data['yes'];
                }
            }
        }
        //生成获得钻石随机分成设定等分
        $sql = "SELECT id,openid,bear_power FROM wemall_user ORDER BY id asc";
        $today_user = $mysqli->query($sql);
        while ($today_users = $today_user->fetch_assoc()) {
            if ($today_users['openid']){
                //用户存在
                $user_id = $today_users['id'];//用户id
                //单个用户动力值
                $sql = "SELECT sum(number) as just_total FROM wemall_bear_power_log WHERE ctime < '$today_time' and user_id='$user_id' and  is_income=1";//个人总收入
                $person_just_total = $mysqli->query($sql);
                $person_just_total = $person_just_total->fetch_assoc();
                $sql = "SELECT sum(number) as negative_total FROM wemall_bear_power_log WHERE ctime < '$today_time' and user_id='$user_id' and is_income=2";//个人总支出
                $person_negative_total = $mysqli->query($sql);
                $person_negative_total = $person_negative_total->fetch_assoc();
                $person_total_list=$person_just_total['just_total']-$person_negative_total['negative_total'];//总收入-总支出
                if ($person_total_list) {
                    $person_total = $person_total_list;//用户的净总动力值(昨天以前的)
                } else {
                    $person_total = 0;
                }
                if ($person_total) {
                    //用户总动力大于0
                    $person_bear_num = $person_total / $total * $today_bear_num;//该用户当日获得的钻石额为:(10/1000)x100;
                    //参加暴击计算
                    if (count($attack_list) > 0) {
                        //有暴击人
                        $flag=0;
                        foreach ($attack_list as $key => $vals) {
                            if ($vals['user_id'] == $user_id) {
                                $flag=$vals['attack'];
                                break;
                            }
                        }
                        if ($flag) {
                            $attack_num =sprintf("%.5f",($person_bear_num / $equal_division) * $flag);//暴击的钻石数
                            $arr_l['val'] = $attack_num;
                            $arr_l['state'] = 1;
                            $arr_l['multiple'] =2;
                            $new_person_bear_num = $person_bear_num - $attack_num;//除去暴击的钻石数量在随机划分
                            $data_bear = getBearNum($new_person_bear_num,$equal_division - 1);
                            $data_bear[] = $arr_l;
                            $bear_num = json_encode($data_bear);
                            $sql = "INSERT INTO wemall_block_chain_list (user_id,ctime,bear_num,multiple) VALUES ('$user_id','$strtime','$bear_num','$flag')";
                            $row = $mysqli->query($sql);
                            if (!$row) {
                                $mysqli->rollback();
                                $result = false;
                                exit;
                            }
                        }else{
                            //不是暴击用户
                            //把获得钻石按设置的随机划分多少份
                            $data_bear = getBearNum($person_bear_num,$equal_division);
                            $bear_num = json_encode($data_bear);
                            $sql = "INSERT INTO wemall_block_chain_list (user_id,ctime,bear_num) VALUES ('$user_id','$strtime','$bear_num')";
                            $row = $mysqli->query($sql);
                            if (!$row) {
                                $mysqli->rollback();
                                $result = false;
                                exit;
                            }
                        }

                    }else{
                        //暴击人数为空
                        //把获得钻石按设置的随机划分多少份
                        $data_bear = getBearNum($person_bear_num,$equal_division);
                        $bear_num = json_encode($data_bear);
                        $sql = "INSERT INTO wemall_block_chain_list (user_id,ctime,bear_num) VALUES ('$user_id','$strtime','$bear_num')";
                        $row = $mysqli->query($sql);
                        if (!$row) {
                            $mysqli->rollback();
                            $result = false;
                            exit;
                        }
                    }
                  }
                }
            }
        }
    }
}
$mysqli->commit();
$mysqli -> close();
function getsum($m,$sum_num,$sum_one){
    //计算暴击人数
    //$sum_num每天产出钻石数量  $sum_one每天产出钻石数量
    for($op=$m-1;$op>=1;$op--){
        $sum_one--;
        $sum_num=$sum_num*$sum_one;
    }
    $sum_two=$m;
    for($pl=$m-1;$pl>0;$pl--){
        $sum_two=$sum_two*$pl;
    }
    if($sum_two&&$sum_num){
        $result=$sum_two*$m/$sum_num;
    }else{
        $result=false;
    }
    return $result;
}
function getnum($list=1,$i=1,$sum_num,$sum_one,$probability){
    if($list<$probability){
        return $i-1;
    }else{
        $lists=getsum($i,$sum_num,$sum_one);
        $i++;
        return(getnum($lists,$i,$sum_num,$sum_one,$probability));
    }
}
function getBearNum($total,$div) {
    //获取昨天钻石数随机分成规定份数   //$total待划分的数字  //$div分成的份数
    $area = ($total/$div)*0.9; //各份数间允许的最大差值
    $average =sprintf("%.5f",$total/$div);
    $sum = 0;
//    $result = array_fill( 1, $div, 0 );
    $result=array();
    for( $i = 1; $i < $div; $i++ ){
        //根据已产生的随机数情况,调整新随机数范围,以保证各份间差值在指定范围内
        if( $sum > 0 ){
            $max = 0;
            $min = 0 - $area/2;
        }elseif( $sum < 0 ){
            $min = 0;
            $max =$area/2;
        }else{
            $max =$area/2;
            $min = 0-$area/2;
        }
        //产生各份的份额
        $random =sprintf("%.5f",$min + mt_rand()/mt_getrandmax() * ($max - $min)) ;
        if($average + $random<0){
            $sum=$sum-$random;
            $result[$i-1]['val']=sprintf("%.5f",$average-$random);
            $result[$i-1]['state']=1;//1 未领取   2已领
            $result[$i-1]['multiple'] =1;//1 没有暴击  2暴击
        }else{
            $sum+=$random;
            $result[$i-1]['val']=sprintf("%.5f",$average+$random);
            $result[$i-1]['state']=1;//1 未领取   2已领
            $result[$i-1]['multiple'] =1;//1 没有暴击  2暴击
        }
    }
    //最后一份的份额由前面的结果决定,以保证各份的总和为指定值
    $result[$div-1]['val']=sprintf("%.5f",$average-$sum);
    $result[$div-1]['state']=1;
    $result[$div-1]['multiple'] =1;//1 没有暴击  2暴击
    //结果呈现
//    $list['value_max']=max($result);  //获取最大值
//    $list['sum']=array_sum($result);
    return $result;
}
function get_rand($arr){
    //抽取用户
    $pro_sum=array_sum($arr);
    $rand_num=mt_rand(1,$pro_sum);
    $tmp_num=0;
    foreach($arr as $k=>$val)
    {
        if($rand_num<=$val+$tmp_num)
        {
            $n=$k;
            break;
        }else
        {
            $tmp_num+=$val;
        }
    }
    return $n;
}
/** 每次前端页面的请求,PHP循环奖项设置数组,
 * 通过概率计算函数get_rand获取抽中的奖项id。
 * 将中奖奖品保存在数组$res['yes']中,
 * 而剩下的未中奖的信息保存在$res['no']中,
 * 最后输出json个数数据给前端页面。
 */
function get_violent_attack($prize_arr){
    //根据熊力大小按概率抽取暴击的用户
    foreach ($prize_arr as $key => $val) {
        $arr[$key+1] = $val['v'];
    }
    $rid =get_rand($arr); //根据概率获取奖项id
    $res['yes'] = $prize_arr[$rid-1]; //中奖项
    unset($prize_arr[$rid-1]); //将中奖项从数组中剔除,剩下未中奖项
    shuffle($prize_arr); //打乱数组顺序
    for($i=0;$i<count($prize_arr);$i++){
        $pr[] = $prize_arr[$i];
    }
    $res['no'] = $pr;//除去中奖的没中用户
    return $res;
}

代码已经在项目运行正常,有不懂的逻辑和算法可以加我的qq:3358756537:

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值