123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351 |
- <?php
- namespace refill;
- use Log;
- class system
- {
- private $mCardType;
- private $mOpened;
- private $mSpecs;
- public function __construct($card_type)
- {
- $this->mCardType = $card_type;
- $this->mSpecs = [];
- $this->mOpened = false;
- }
- public function card_type() {
- return $this->mCardType;
- }
- public function add_amount($amount)
- {
- $this->mSpecs[] = $amount;
- }
- public function set_opened($opened) {
- $this->mOpened = $opened;
- }
- public function opened() : bool {
- return $this->mOpened;
- }
- public function total()
- {
- $amounts = 0;
- foreach ($this->mSpecs as $spec) {
- $amount = rlock::hget_sys_storage($this->mCardType,$spec);
- $amount = intval($amount);
- $amount = $amount > 0 ? $amount : 0;
- $amounts += $amount;
- }
- return $amounts;
- }
- public function spec_total($spec)
- {
- $amount = rlock::hget_sys_storage($this->mCardType,$spec);
- $amount = intval($amount);
- return $amount > 0 ? $amount : 0;
- }
- }
- class merchant
- {
- private $mMchid;
- private $mTotalLocks;
- private $mSpecLocks;
- public function __construct($mchid)
- {
- $this->mMchid = $mchid;
- $this->mTotalLocks = [];
- $this->mSpecLocks = [];
- }
- public function mchid() {
- return $this->mMchid;
- }
- public function set_total_lock($card_type, $lock_type)
- {
- if ($lock_type != rlock::CLOSE) {
- $this->mTotalLocks[$card_type] = $lock_type;
- }
- }
- public function total($card_type)
- {
- if(array_key_exists($card_type,$this->mTotalLocks)) {
- $amount = rlock::hget_mch_total_storage($this->mMchid,$card_type);
- $amount = intval($amount);
- return $amount > 0 ? $amount : 0;
- }
- elseif(array_key_exists($card_type, $this->mSpecLocks))
- {
- $specs = $this->mSpecLocks[$card_type];
- $amounts = 0;
- foreach ($specs as $spec) {
- $amounts += $this->spec_total($card_type,$spec);
- }
- return $amounts;
- }
- else {
- return 0;
- }
- }
- public function spec_total($card_type,$spec)
- {
- if (array_key_exists($card_type, $this->mSpecLocks) && array_key_exists($spec, $this->mSpecLocks[$card_type])) {
- $amount = rlock::hget_mch_storage($this->mMchid, $card_type, $spec);
- $amount = intval($amount);
- return $amount > 0 ? $amount : 0;
- } else {
- return 0;
- }
- }
- public function set_spec_lock($card_type,$spec,$lock_type)
- {
- if ($lock_type != rlock::CLOSE) {
- $this->mSpecLocks[$card_type][$spec] = $lock_type;
- }
- }
- public function has_lock()
- {
- return !empty($this->mTotalLocks) || !empty($this->mSpecLocks);
- }
- public function lock_type($card_type,$spec)
- {
- $total_lock = rlock::CLOSE;
- if(array_key_exists($card_type,$this->mTotalLocks)) {
- $total_lock = $this->mTotalLocks[$card_type];
- }
- $spec_lock = rlock::CLOSE;
- if(array_key_exists($card_type,$this->mSpecLocks) && array_key_exists($spec,$this->mSpecLocks[$card_type])) {
- $spec_lock = $this->mSpecLocks[$card_type][$spec];
- }
- return [$total_lock,$spec_lock];
- }
- }
- class rstorage
- {
- private $mSystems;
- private $mMerchants;
- public function __construct()
- {
- $this->mSystems = [];
- $this->mMerchants = [];
- }
- public function load()
- {
- $this->mSystems = [];
- $this->read_sys();
- $this->mMerchants = [];
- $this->read_merchant();
- }
- private function locked($card_type)
- {
- if(array_key_exists($card_type,$this->mSystems)) {
- return true;
- } else {
- return false;
- }
- }
- public function allow($mchid,$card_type,$spec) : bool
- {
- Log::record("rstorage::allow mchid={$mchid} card_type={$card_type} spec={$spec}",Log::DEBUG);
- if(!$this->locked($card_type)) {
- Log::record("rstorage::allow {$card_type} locked",Log::DEBUG);
- return true;
- }
- [$total_lock_type,$spec_lock_type] = $this->merchant_lock_type($mchid,$card_type,$spec);
- $merchant = $this->mMerchants[$mchid];
- Log::record("{$mchid} total_lock:{$total_lock_type} spec_lock:{$spec_lock_type}",Log::DEBUG);
- if($spec_lock_type == rlock::ASSIGN) {
- $mch_spec_total = $merchant->spec_total($spec);
- Log::record("ASSIGN {$mchid} spec_total:{$mch_spec_total}",Log::DEBUG);
- return $mch_spec_total >= $spec;
- }
- elseif($spec_lock_type == rlock::RETAIN)
- {
- //是否已经满足 Spec
- $mch_spec_total = $merchant->spec_total($card_type);
- Log::record("ASSIGN {$mchid} spec_total:{$mch_spec_total}",Log::DEBUG);
- if($mch_spec_total >= $spec) return true;
- }
- else {
- //CLOSE情况,其它两种情况优先。
- }
- if ($total_lock_type == rlock::ASSIGN) {
- $mch_total = $merchant->total($card_type);
- if($mch_total < $spec) return false;
- }
- $system = $this->mSystems[$card_type];
- $total = $system->total();
- $spec_total = $system->spec_total($spec);
- $diff_total = $total - $this->lowest_total($mchid,$card_type);
- $diff_spec_total = $spec_total - $this->lowest_spec_total($mchid,$card_type,$spec);
- Log::record("mchid:{$mchid} total:{$total} spec_total:{$spec_total} diff_total:{$diff_total} diff_spec_total={$diff_spec_total}",Log::DEBUG);
- return $diff_spec_total >= $spec && $diff_total >= $spec;
- }
- //return [$toal_lock,$spec_lock]
- private function merchant_lock_type($mchid, $card_type, $spec)
- {
- if(!array_key_exists($mchid,$this->mMerchants)) {
- return [rlock::CLOSE,rlock::CLOSE];
- }
- $merchant = $this->mMerchants[$mchid];
- return $merchant->lock_type($card_type, $spec);
- }
- //需要为锁定的机构保留的最低总量
- private function lowest_total($mchid,$card_type)
- {
- $total = 0;
- foreach ($this->mMerchants as $merchant)
- {
- if($mchid != $merchant->mchid()){
- $total += $merchant->total($card_type);
- }
- }
- return $total;
- }
- //需要为锁定的机构保留的最低总量
- private function lowest_spec_total($mchid,$card_type,$spec)
- {
- $total = 0;
- foreach ($this->mMerchants as $merchant)
- {
- if($mchid != $merchant->mchid()){
- $total += $merchant->spec_total($card_type,$spec);
- }
- }
- return $total;
- }
- private function read_sys()
- {
- $items = rlock::get_sys();
- $parser = function ($key,$val)
- {
- $datas = explode('-',$key);
- $len = count($datas);
- if($len != 2) return [false,'','',''];
- $card_type = intval($datas[0]);
- if($datas[1] == 'open') {
- return [true,'open',$card_type,boolval($val)];
- }
- elseif(is_numeric($datas[1])) {
- return [true,'card',$card_type,intval($datas[1])];
- }
- else {
- return [false,'','',''];
- }
- };
- $systems = [];
- foreach ($items as $key => $val)
- {
- [$succ,$name,$card_type,$value] = $parser($key,$val);
- if($succ)
- {
- if(array_key_exists($card_type,$systems)) {
- $system = $systems[$card_type];
- } else {
- $system = new system($card_type);
- $systems[$card_type] = $system;
- }
- if($name == 'open') {
- $system->set_opened($value);
- }
- elseif($name == 'card') {
- $system->add_amount($value);
- }
- }
- }
- foreach ($systems as $system)
- {
- if($system->opened()) {
- $card_type = $system->card_type();
- $this->mSystems[$card_type] = $system;
- }
- }
- }
- private function read_merchant()
- {
- $parser = function ($key,$val,&$merchants)
- {
- $items = explode('-',$key);
- $len = count($items);
- if($len < 3) return;
- $mchid = intval($items[0]);
- if(array_key_exists($mchid,$merchants)) {
- $merchant = $merchants[$mchid];
- } else {
- $merchant = new merchant($mchid);
- $merchants[$mchid] = $merchant;
- }
- $card_type = intval($items[1]);
- if($len == 3)
- {
- if($items[2] == 'turn') {
- $lock_type = intval($val);
- $merchant->set_total_lock($card_type,$lock_type);
- }
- }
- elseif($len == 4)
- {
- $amount = intval($items[2]);
- if($items[3] == 'turn') {
- $lock_type = intval($val);
- $merchant->set_spec_lock($card_type,$amount,$lock_type);
- }
- }
- };
- $merchants = [];
- $items = rlock::get_merchant();
- foreach ($items as $key => $val) {
- $parser($key, $val, $merchants);
- }
- foreach ($merchants as $merchant)
- {
- if($merchant->has_lock()) {
- $mchid = $merchant->mchid();
- $this->mMerchants[$mchid] = $merchant;
- }
- }
- }
- }
|