Browse Source

增加H5红包摇一摇功能

stanley-king 8 years atrás
parent
commit
2783bad628

+ 1 - 1
core/33hao.php

@@ -16,7 +16,7 @@ if (file_exists(BASE_PATH.'/config/config.ini.php')){
 
 @date_default_timezone_set('Asia/Shanghai');
 
-global $config;
+//global $config;
 //默认平台店铺id
 define('DEFAULT_PLATFORM_STORE_ID', $config['default_store_id']);
 

+ 0 - 1
data/model/user_bonus.model.php

@@ -47,7 +47,6 @@ class user_bonusModel extends Model
     }
 
     //public function luckey
-
     public function add($datas) {
         return $this->insert($datas);
     }

+ 90 - 0
helper/bonus/allocator.php

@@ -0,0 +1,90 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: stanley-king
+ * Date: 16/6/21
+ * Time: 下午4:01
+ */
+
+namespace bonus;
+
+
+class allocator
+{
+    private function get_maxamount($total,$num)
+    {
+        $avg = floatval($total / $num);
+        return intval($avg * 2 + 0.5);
+    }
+
+    private function get_minamount($total,$num)
+    {
+        $avg = floatval($total / $num);
+        $avg = $avg / 10;
+        $avg = intval($avg + 0.5);
+
+        return $avg;
+    }
+    /**
+     * @param $paramer
+     */
+    public function separate_money($min_amount,$total_amount,$total_num,&$min_val,&$max_val)
+    {
+        $min_amount = intval(floatval($min_amount) * 100 + 0.5);
+        $base_amount = $min_amount;
+        $num = intval($total_num);
+
+        $ret = array();
+        for ($i = 0; $i < $num; $i++) {
+            array_push($ret,$base_amount);
+        }
+
+        $total_amount = intval(intval(floatval($total_amount) * 100 + 0.5) - $num * $base_amount);
+        $min_amount = $this->get_minamount($total_amount,$num);
+
+        if($min_amount > 0)
+        {
+            foreach($ret as &$val) {
+                $val += $min_amount;
+            }
+            $total_amount -= $min_amount * $num;
+        }
+
+        $max_val = 0;
+        $max_amount = $this->get_maxamount($total_amount,$num);
+        for ($i = 0; $i < $num && $total_amount > 0;)
+        {
+            $amount = intval(mt_rand(0, $max_amount));
+            $amount = $amount > $total_amount ? $total_amount : $amount;
+
+            $ret[$i] += $amount;
+            $total_amount -= $amount;
+            $max_val = $ret[$i] > $max_val ? $ret[$i] : $max_val;
+
+            if($i == $num -1) {
+                $i = 0;
+            } else {
+                $i++;
+            }
+        }
+
+        $max_val = floatval($max_val) / 100;
+        $min_val = $ret[0];
+        foreach ($ret as &$val) {
+            $min_val = $min_val > $val ? $val : $min_val;
+            $val = floatval($val) / 100;
+        }
+        $min_val = floatval($min_val) / 100;
+
+        for($index = 0; $index < $num - 1; $index++) {
+            $pos_a = mt_rand(0, $num - 1);
+            $pos_b = mt_rand(0, $num - 1);
+
+            $tmp = $ret[$pos_a];
+            $ret[$pos_a] = $ret[$pos_b];
+            $ret[$pos_b] = $tmp;
+        }
+
+        return $ret;
+    }
+}

+ 2 - 78
helper/bonus/generator.php

@@ -66,7 +66,8 @@ class GeneralGenerator extends IGenerator
 
         if($this->mType->isRandomAmount())
         {
-            $moneys = $this->separate_money($paramer,$min_val,$max_val);
+            $allocator = new allocator();
+            $moneys = $allocator->separate_money($paramer['min_amount'],$paramer['total_amount'],$paramer['total_num'],$min_val,$max_val);
             Model('bonus_type')->edit(array('type_id' => $type_id),array('min_amount' => $min_val,'max_amount' => $max_val));
 
             foreach($moneys as $val)
@@ -103,83 +104,6 @@ class GeneralGenerator extends IGenerator
 
         return true;
     }
-
-    private function get_maxamount($total,$num)
-    {
-        $avg = floatval($total / $num);
-        return intval($avg * 2 + 0.5);
-    }
-
-    private function get_minamount($total,$num)
-    {
-        $avg = floatval($total / $num);
-        $avg = $avg / 10;
-        $avg = intval($avg + 0.5);
-
-        return $avg;
-    }
-    /**
-     * @param $paramer
-     */
-    private function separate_money($paramer,&$min_val,&$max_val)
-    {
-        $min_amount = intval(floatval($paramer['min_amount']) * 100 + 0.5);
-        $base_amount = $min_amount;
-        $num = intval($paramer['total_num']);
-
-        $ret = array();
-        for ($i = 0; $i < $num; $i++) {
-            array_push($ret,$base_amount);
-        }
-
-        $total_amount = intval(intval(floatval($paramer['total_amount']) * 100 + 0.5) - $num * $base_amount);
-        $min_amount = $this->get_minamount($total_amount,$num);
-
-        if($min_amount > 0)
-        {
-            foreach($ret as &$val) {
-                $val += $min_amount;
-            }
-            $total_amount -= $min_amount * $num;
-        }
-
-        $max_val = 0;
-        $max_amount = $this->get_maxamount($total_amount,$num);
-        for ($i = 0; $i < $num && $total_amount > 0;)
-        {
-            $amount = intval(mt_rand(0, $max_amount));
-            $amount = $amount > $total_amount ? $total_amount : $amount;
-
-            $ret[$i] += $amount;
-            $total_amount -= $amount;
-            $max_val = $ret[$i] > $max_val ? $ret[$i] : $max_val;
-
-            if($i == $num -1) {
-                $i = 0;
-            } else {
-                $i++;
-            }
-        }
-
-        $max_val = floatval($max_val) / 100;
-        $min_val = $ret[0];
-        foreach ($ret as &$val) {
-            $min_val = $min_val > $val ? $val : $min_val;
-            $val = floatval($val) / 100;
-        }
-        $min_val = floatval($min_val) / 100;
-
-        for($index = 0; $index < $num - 1; $index++) {
-            $pos_a = mt_rand(0, $num - 1);
-            $pos_b = mt_rand(0, $num - 1);
-
-            $tmp = $ret[$pos_a];
-            $ret[$pos_a] = $ret[$pos_b];
-            $ret[$pos_b] = $tmp;
-        }
-
-        return $ret;
-    }
 }
 
 

+ 42 - 0
helper/bonus/manager.php

@@ -149,6 +149,7 @@ class manager
         return $bonus;
     }
 
+
     public function grab_bonus($type_sn)
     {
         $bonus = $this->read_session($type_sn);
@@ -246,6 +247,47 @@ class manager
         return true;
     }
 
+    public function shake($bonus_sn,$strength,$direction)
+    {
+        $bonus_info = self::read_session('',$bonus_sn);
+        if(!empty($bonus_info))
+        {
+            $user_bonus = user_bonus::create_by_param($bonus_info);
+            $bonus_id = $user_bonus->bonus_id();
+            $type_id = $user_bonus->type_id();
+            $bonus_val = $user_bonus->bonus_value();
+        }
+
+        if(!isset($type_id))
+        {
+            $user_bonus = user_bonus::create_by_sn($bonus_sn);
+            if(!$user_bonus->isBinded()) {
+                return false;
+            }
+
+            $bonus_id = $user_bonus->bonus_id();
+            $type_id = $user_bonus->type_id();
+            $bonus_val = $user_bonus->bonus_value();
+        }
+
+        $shaker = new \bonus\shaker();
+        $ret = $shaker->reassign($type_id,$bonus_id,$bonus_val,$strength,$direction);
+        if($ret == true)
+        {
+            $bonus = $this->read_session('',$bonus_sn);
+            if(!empty($bonus)) {
+                $this->clear_session($bonus_sn);
+                $bonus['bonus_value'] = $bonus_val;
+                $this->write_session($bonus);
+            }
+            dcache($user_bonus->type_sn(),self::type_prefix);
+            
+            return true;
+        } else {
+            return false;
+        }
+    }
+
     public function comment($bonus_sn,$content)
     {
         if(empty($bonus_sn)) return false;

+ 182 - 0
helper/bonus/shaker.php

@@ -0,0 +1,182 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: stanley-king
+ * Date: 16/6/21
+ * Time: 下午1:07
+ */
+
+namespace bonus;
+
+use \Exception;
+use \Db;
+
+class shaker
+{
+    const max_strength = 5;
+    const min_amount = 0.01;
+
+    const direct_asc = 0;
+    const direct_dec = 1;
+
+    public function reassign($type_id,$bonus_id,&$bonus_valin,$strength,$direction)
+    {
+        try
+        {
+            $bonus_val = $bonus_valin;
+            Db::beginTransaction();
+
+            $mod_bonus = Model('user_bonus');
+
+            $min_amount = self::min_amount;
+            $items = $mod_bonus->get(array('type_id' => $type_id,'bonus_status' => 0,'bonus_value' => array('gt',$min_amount)));
+            if(!empty($items))
+            {
+                $total_num = $this->weight_num($strength,count($items));
+
+                $total_amount = 0;
+                $index = 0;
+                $selitems = array();
+                foreach ($items as $bonus)
+                {
+                    $total_amount += intval($bonus['bonus_value'] * 100 + 0.5);
+                    array_push($selitems,$bonus);
+
+                    if(++$index >= $total_num) {
+                        break;
+                    }
+                }
+
+                $total_amount = floatval($total_amount / 100);
+                $ret = $this->separate($bonus_val,$total_amount,$total_num,$direction,$strength);
+                if($ret == true)
+                {
+                    $type = type::create_by_id($type_id);
+                    $type_max_value = $type->max_amount();
+
+                    $alloc = new allocator();
+                    $moneys = $alloc->separate_money(self::min_amount,$total_amount,$total_num,$min_val,$max_val);
+
+                    $ret = $mod_bonus->where(array('type_id' => $type_id,'bonus_id' => $bonus_id))->update(array('bonus_value' => $bonus_val));
+                    if($ret == false || $mod_bonus->affected_rows() <= 0) {
+                        throw new Exception();
+                    }
+
+                    $index = 0;
+                    $max_value = 0.00;
+                    foreach ($selitems as &$item) {
+                        $item['bonus_value'] = $moneys[$index];
+                        $max_value = $this->max($max_val,$item['bonus_value']);
+                        ++$index;
+                    }
+                    $type_max_value = $this->max($type_max_value,$max_value);
+                    $remain_change = $bonus_val - $bonus_valin;
+                    Model('bonus_type')->edit(array('type_id' => $type_id),
+                        array('max_amount' => $type_max_value,
+                              'remain_amount' => array('exp', "remain_amount-" . "{$remain_change}"))
+                    );
+
+                    $ret = $mod_bonus->insertAll($selitems,array(),true);
+                    if($ret == false && $mod_bonus->affected_rows() <= 0) {
+                        throw new Exception();
+                    }
+                }
+            }
+
+            Db::commit();
+            $bonus_valin = $bonus_val;
+            return true;
+        }
+        catch (Exception $ex) {
+            Db::rollback();
+            return false;
+        }
+    }
+
+    private function max($left,$right)
+    {
+        $left = intval($left * 100 + 0.5);
+        $right = intval($right * 100 + 0.5);
+
+        return $left > $right ? $left / 100 : $right / 100;
+    }
+
+    private function delta_asc($total,$num,$strength)
+    {
+        if($strength == 5) {
+            $mul = 2;
+        } elseif ($strength == 4) {
+            $mul = 1.6;
+        } elseif ($strength == 3) {
+            $mul = 1.2;
+        } elseif ($strength == 2) {
+            $mul = 0.8;
+        } elseif ($strength == 1) {
+            $mul = 0.4;
+        } else {
+            return 0;
+        }
+
+        $avg = floatval($total / $num);
+        $avg = intval($avg * $mul + 0.5);
+        return mt_rand(0,$avg);
+    }
+
+    private function delta_dec($total,$strength)
+    {
+        if($strength == 5) {
+            $mul = 1;
+        } elseif ($strength == 4) {
+            $mul = 0.8;
+        } elseif ($strength == 3) {
+            $mul = 0.6;
+        } elseif ($strength == 2) {
+            $mul = 0.4;
+        } elseif ($strength == 1) {
+            $mul = 0.2;
+        } else {
+            return 0;
+        }
+
+        $avg = intval($total * $mul + 0.5);
+        return mt_rand(0,$avg);
+    }
+
+
+    private function weight_num($strength,$total_num)
+    {
+        if($strength == 0) {
+            $strength = 1;
+        }
+
+        $weight = intval(floatval($total_num / self::max_strength) * $strength + 0.5);
+        return ($weight > $total_num) ? $total_num : $weight;
+    }
+
+    private function separate(&$bonus_out,&$total_amount,$total_num,$direction,$strength)
+    {
+        $total_tmp = intval($total_amount * 100 + 0.5);
+        $bonus_val = intval($bonus_out * 100 + 0.5);
+
+        $min_amount = 1;
+        $base_amount = $min_amount * $total_num;
+
+        if($base_amount == $total_tmp) {
+            return false;
+        }
+
+        if($direction == self::direct_asc) { //金额变大
+            $delta = $this->delta_asc($total_tmp - $base_amount,$total_num + 1, $strength);
+            $bonus_val += $delta;
+            $total_tmp = $total_tmp - $delta;
+        } else { //金额变小
+            $delta = $this->delta_dec($bonus_val - self::min_amount, $strength);
+            $bonus_val -= $delta;
+            $total_tmp = $total_tmp + $delta;
+        }
+        $total_amount = $total_tmp / 100;
+        $bonus_out = $bonus_val / 100;
+
+        return true;
+    }
+}

+ 17 - 0
helper/bonus_helper.php

@@ -14,6 +14,10 @@ require_once (BASE_ROOT_PATH . '/helper/bonus/grab.php');
 require_once (BASE_ROOT_PATH . '/helper/bonus/bind.php');
 require_once (BASE_ROOT_PATH . '/helper/bonus/factory.php');
 require_once (BASE_ROOT_PATH . '/helper/bonus/manager.php');
+require_once (BASE_ROOT_PATH . '/helper/bonus/shaker.php');
+require_once (BASE_ROOT_PATH . '/helper/bonus/shaker.php');
+require_once (BASE_ROOT_PATH . '/helper/bonus/allocator.php');
+
 require_once (BASE_ROOT_PATH . '/helper/field_helper.php');
 require_once (BASE_ROOT_PATH . '/helper/predeposit_helper.php');
 
@@ -102,6 +106,12 @@ class bonus_helper
             return array($ex->getCode(),$ex->getMessage());
         }
     }
+    static public function shake($bonus_sn,$strength,$direction)
+    {
+        $manager = new \bonus\manager();
+        return $manager->shake($bonus_sn,$strength,$direction);
+    }
+
     static public function comment($bonus_sn,$comment)
     {
         try
@@ -243,4 +253,11 @@ class bonus_helper
 
         return $param;
     }
+
+    static public function direct_asc() {
+        return \bonus\shaker::direct_asc;
+    }
+    static public function direct_dec() {
+        return \bonus\shaker::direct_dec;
+    }
 }

+ 46 - 0
mobile/control/bonusex.php

@@ -269,6 +269,52 @@ class bonusexControl extends mobileControl
         }
     }
 
+    public function shakeOp()
+    {
+        if(!isset($_GET['bonus_sn']) || empty($_GET['bonus_sn'])) {
+            return self::outerr(errcode::ErrParamter,"请输入红包序列号.");
+        }
+        $bonus_sn = $_GET['bonus_sn'];
+        $mine_bonus = bonus_helper::get_mine_by_bonussn($bonus_sn);
+        if($mine_bonus == false) {
+            return self::outerr(errcode::ErrParamter, "领到红包后才可以摇.");
+        }
+
+        if(!isset($_POST['strength']) || empty($_POST['strength'])) {
+            $strength = intval($_POST['strength']);
+        } else {
+            $strength = 3;
+        }
+
+        $bonus_obj = \bonus\user_bonus::create_by_param($mine_bonus);
+        if($bonus_obj->isBinded())
+        {
+            $type_sn = $bonus_obj->type_sn();
+            $type_infos = bonus_helper::get_typeinfo($type_sn);
+            $type = \bonus\type::crate_by_paramer($type_infos['type_info']);
+            if($type->isEnd()) {
+                return self::outsuccess(errcode::ErrBonus,"该红包已经过期,不能再摇啦~");
+            }
+            elseif($type->binded_over()) {
+                return self::outsuccess(errcode::ErrBonus,"该红包已经被领光,摇不出更多啦~");
+            }
+            elseif($type->isFixedAmount()) {
+                return self::outsuccess(errcode::ErrBonus,"只有拼收起红包才可以摇哦~");
+            }
+            else {
+                $direction = bonus_helper::direct_dec();
+                $ret = bonus_helper::shake($bonus_obj->bonus_sn(),$strength,$direction);
+                if($ret == true) {
+                    $bonus = bonus_helper::get_mine_by_bonussn($bonus_obj->bonus_sn());
+                }
+            }
+            //return self::outsuccess(array('type_info' => $type_info, 'mine_bonus' => $mine_bonus,'binded_info' => $binded_info),"bonus/content");
+        }
+        else {
+            return self::outerr(errcode::ErrParamter, "领到红包后才可以摇.");
+        }
+    }
+
     //红包留言
     public function commentOp()
     {

+ 1 - 0
mobile/util/errcode.php

@@ -66,6 +66,7 @@ class errcode extends SplEnum
     const ErrBonusSN = 10805;
     const ErrBonusBinded = 10806;
     const ErrBonusComment = 10807;
+    const ErrBonusShake = 10808;
 
     //套装
     const ErrBLUnExist = 10900;

+ 1 - 1
run.php

@@ -5,7 +5,7 @@ define('BASE_ROOT_PATH',str_replace('\\','/',dirname(__FILE__)));
 
 require_once(BASE_ROOT_PATH . '/fooder.php');
 
-$gfcgi_run = 1;
+$gfcgi_run = 2;
 
 if($gfcgi_run == 0) { //模拟请求
     $file = BASE_ROOT_PATH . '/debug_run.php';

+ 34 - 0
test/bonus_helperTest.php

@@ -0,0 +1,34 @@
+<?php
+
+/**
+ * Created by PhpStorm.
+ * User: stanley-king
+ * Date: 16/6/21
+ * Time: 下午8:28
+ */
+
+define('BASE_ROOT_PATH',str_replace('/test','',dirname(__FILE__)));
+
+require_once(BASE_ROOT_PATH . '/fooder.php');
+require_once(BASE_ROOT_PATH . '/helper/bonus_helper.php');
+
+
+class bonus_helperTest extends PHPUnit_Framework_TestCase
+{
+    public static function setUpBeforeClass()
+    {
+        Base::run_util();
+    }
+
+    public function testModel()
+    {
+        $item = Model('user_bonus')->field('*')->where(array('type_id' => 105,'bonus_id' => 2491))->select();
+        bonus_helper::shake($item[0]['type_id'],$item[0]['bonus_id'],$item[0]['bonus_value'],3,bonus_helper::direct_dec());
+
+    }
+    public static function tearDownAfterClass()
+    {
+
+    }
+
+}