-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathreward.php
167 lines (157 loc) · 5.94 KB
/
reward.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
<?php
require_once 'RandReward.php';
class Reward
{
public $redis;
public $square;
public function __construct($type)
{
$redis = new Redis();
$redis->connect("127.0.0.1", 6379);
$this->redis = $redis;
$this->square = $type . ":rewards_square";
}
public function createReward($user_id, $data = array())
{
$redis = $this->redis;
//$reward_id = $redis->incr($this->square);
$reward_id = $data['reward_id'];
// 红包信息(hash)
$reward_key = $reward_id . ":info";
foreach ($data as $key => $value) {
$redis->hset($reward_key, $key, $value);
}
//个人红包列表 set
$person_rewards = $user_id . ":reward";
$redis->sadd($person_rewards, $reward_id);
//随机小红包列表(list)
/* $rand_reward_array = $this->splitReward($reward_id, $data['money'], $data['total_num']);*/
$pipe = $redis->multi(Redis::PIPELINE);
$rand_reward = new RandReward();
$rand_reward_array = $rand_reward->splitReward($data['money'], $data['total_num'], 100);
$rand_reward_list = $reward_id . ":splite_list";
foreach ($rand_reward_array as $item) {
/*$this->log('list_________', $item);*/
$pipe->lpush($rand_reward_list, $item);
}
/*$redis->lRange($rand_reward_list, 0, -1);*/
//红包添加红包广场
$pipe->zadd($this->square, time(), $reward_id);
$pipe->exec();
$this->log("reward_id", $data);
}
public function getRewardSpliteList($reward_id, $data)
{
$redis = $this->redis;
$rand_reward_array = $this->splitReward($reward_id, $data['money'], $data['total_num']);
$rand_reward_list = $reward_id . ":splite_list";
foreach ($rand_reward_array as $item) {
$redis->lpush($rand_reward_list, $item);
}
}
//红包广场信息
public function getRewardSquare($start, $end)
{
$redis = $this->redis;
$square = $this->square;
$reward_ids = $redis->zrevrange($square, $start, $end);
$square_data = array();
$time = time();
$this->log("<<<<<<<<<<<<红包广场信息", "单个红包信息");
foreach ($reward_ids as $item) {
$reward = $redis->hgetall($item . ":info");
/*if($time - $red_pocket['create_time'] >172800){
$square_data[] = $red_pocket;
}*/
$this->log('红包信息: ', $reward);
$square_data[] = $reward;
}
$this->log("红包广场信息", ">>>>>>>>>>>>>");
return $square_data;
}
//领取红包
public function gainReward($user_id, $reward_id)
{
$redis = $this->redis;
$reward_splite_list = $reward_id . ":splite_list";
$reward_record = $reward_id . ":record";
$reward_key = $reward_id . ":info";
/*$red_pocket = $red_pocket_id;*/
if ($redis->sismember($reward_record, $user_id)) {
$this->log("------你已经领取过了-------", "");
return;
}
while (true) {
$redis->watch($reward_key);
$rest_num = $redis->hget($reward_key, "rest_num");
$this->log("------剩余个数-----", $rest_num);
$lose_num = $redis->hget($reward_key, "lose_num");
$this->log("------领取个数-----", $lose_num);
$total_num = $redis->hget($reward_key, "total_num");
$this->log("------总个数-----", $total_num);
if ($rest_num - 1 >= 0) {
$redis->multi();
$redis->RPOP($reward_splite_list);
$redis->hincrby($reward_key, "rest_num", -1);
$redis->hincrby($reward_key, "lose_num", 1);
$result = $redis->exec();
if ($result) {
$redis->sadd($reward_record, $user_id);
$this->log("-----------恭喜领到红包---------用户id:$user_id 金额: ", $result[0]);
break;
}
} else {
$this->log("-------红包已经领完了-------", "");
return;
}
}
}
// 获取红包信息
public function getRewardData($reward_id)
{
$redis = $this->redis;
$reward_pocket = $redis->hgetall($reward_id);
$reward_record = $reward_id . ":record";
$user_ids = $redis->smembers($reward_record);
$data['reward_info'] = $reward_pocket;
$data['gain_info'] = array();
$this->log('红包信息', $data);
return $data;
}
public function splitReward($reward_id, $money, $total_num)
{
$money = (int)($money * 100);
if ($total_num <= 0) {
return;
}
if ($money < $total_num) {
return;
}
$frozen_money = $total_num;
$assign_money = $money - $frozen_money;
$weights = [];
$weight_sum = 0;
for ($i = 0; $i < $total_num; $i++) {
$weight = pow(mt_rand(0, 999), 1.5);
$weights[] = $weight;
$weight_sum += $weight;
}
// 按权数分配金额,向下取整以避免分配金额超过总金额
$moneys = [];
$money_sum = 0;
foreach ($weights as $weight) {
$money = (int)($weight / $weight_sum * $assign_money) + 1; // +1是将冻结的金额补上
$moneys[] = $money;
$money_sum += $money;
}
// 由于分配时向下取整实际分配数小于总金额,随机挑选一人,将未分配的金额分配到此人
$lucky_num = mt_rand(0, $total_num - 1); // 幸运者序号
$rest_money = $money - $money_sum; // 未分配金额
$moneys[$lucky_num] += $rest_money;
return $moneys;
}
public function log($msg, $data)
{
file_put_contents("output.log", $msg . "********" . json_encode($data) . PHP_EOL, FILE_APPEND);
}
}