|
@@ -0,0 +1,329 @@
|
|
|
+<?php
|
|
|
+
|
|
|
+namespace refill;
|
|
|
+
|
|
|
+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;
|
|
|
+ }
|
|
|
+ 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->load();
|
|
|
+ }
|
|
|
+
|
|
|
+ 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
|
|
|
+ {
|
|
|
+ if(!$this->locked($card_type)) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ [$total_lock_type,$spec_lock_type] = $this->merchant_lock_type($mchid,$card_type,$spec);
|
|
|
+ $merchant = $this->mMerchants[$mchid];
|
|
|
+
|
|
|
+ if($spec_lock_type == rlock::ASSIGN) {
|
|
|
+ return $merchant->spec_total($spec) >= $spec;
|
|
|
+ }
|
|
|
+ elseif($spec_lock_type == rlock::RETAIN)
|
|
|
+ {
|
|
|
+ //是否已经满足 Spec
|
|
|
+ $mch_spec_total = $merchant->spec_total($card_type);
|
|
|
+ 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);
|
|
|
+
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|