rstorage.php 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. <?php
  2. namespace refill;
  3. class system
  4. {
  5. private $mCardType;
  6. private $mOpened;
  7. private $mSpecs;
  8. public function __construct($card_type)
  9. {
  10. $this->mCardType = $card_type;
  11. $this->mSpecs = [];
  12. $this->mOpened = false;
  13. }
  14. public function card_type() {
  15. return $this->mCardType;
  16. }
  17. public function add_amount($amount)
  18. {
  19. $this->mSpecs[] = $amount;
  20. }
  21. public function set_opened($opened) {
  22. $this->mOpened = $opened;
  23. }
  24. public function opened() : bool {
  25. return $this->mOpened;
  26. }
  27. public function total()
  28. {
  29. $amounts = 0;
  30. foreach ($this->mSpecs as $spec) {
  31. $amount = rlock::hget_sys_storage($this->mCardType,$spec);
  32. $amount = intval($amount);
  33. $amount = $amount > 0 ? $amount : 0;
  34. $amounts += $amount;
  35. }
  36. return $amounts;
  37. }
  38. public function spec_total($spec)
  39. {
  40. $amount = rlock::hget_sys_storage($this->mCardType,$spec);
  41. $amount = intval($amount);
  42. return $amount > 0 ? $amount : 0;
  43. }
  44. }
  45. class merchant
  46. {
  47. private $mMchid;
  48. private $mTotalLocks;
  49. private $mSpecLocks;
  50. public function __construct($mchid)
  51. {
  52. $this->mMchid = $mchid;
  53. $this->mTotalLocks = [];
  54. $this->mSpecLocks = [];
  55. }
  56. public function mchid() {
  57. return $this->mMchid;
  58. }
  59. public function set_total_lock($card_type, $lock_type)
  60. {
  61. if ($lock_type != rlock::CLOSE) {
  62. $this->mTotalLocks[$card_type] = $lock_type;
  63. }
  64. }
  65. public function total($card_type)
  66. {
  67. if(array_key_exists($card_type,$this->mTotalLocks)) {
  68. $amount = rlock::hget_mch_total_storage($this->mMchid,$card_type);
  69. $amount = intval($amount);
  70. return $amount > 0 ? $amount : 0;
  71. }
  72. else {
  73. return 0;
  74. }
  75. }
  76. public function spec_total($card_type,$spec)
  77. {
  78. if (array_key_exists($card_type, $this->mSpecLocks) && array_key_exists($spec, $this->mSpecLocks[$card_type])) {
  79. $amount = rlock::hget_mch_storage($this->mMchid, $card_type, $spec);
  80. $amount = intval($amount);
  81. return $amount > 0 ? $amount : 0;
  82. } else {
  83. return 0;
  84. }
  85. }
  86. public function set_spec_lock($card_type,$spec,$lock_type)
  87. {
  88. if ($lock_type != rlock::CLOSE) {
  89. $this->mSpecLocks[$card_type][$spec] = $lock_type;
  90. }
  91. }
  92. public function has_lock()
  93. {
  94. return !empty($this->mTotalLocks) || !empty($this->mSpecLocks);
  95. }
  96. public function lock_type($card_type,$spec)
  97. {
  98. $total_lock = rlock::CLOSE;
  99. if(array_key_exists($card_type,$this->mTotalLocks)) {
  100. $total_lock = $this->mTotalLocks[$card_type];
  101. }
  102. $spec_lock = rlock::CLOSE;
  103. if(array_key_exists($card_type,$this->mSpecLocks) && array_key_exists($spec,$this->mSpecLocks[$card_type])) {
  104. $spec_lock = $this->mSpecLocks[$card_type][$spec];
  105. }
  106. return [$total_lock,$spec_lock];
  107. }
  108. }
  109. class rstorage
  110. {
  111. private $mSystems;
  112. private $mMerchants;
  113. public function __construct()
  114. {
  115. $this->load();
  116. }
  117. public function load()
  118. {
  119. $this->mSystems = [];
  120. $this->read_sys();
  121. $this->mMerchants = [];
  122. $this->read_merchant();
  123. }
  124. private function locked($card_type)
  125. {
  126. if(array_key_exists($card_type,$this->mSystems)) {
  127. return true;
  128. } else {
  129. return false;
  130. }
  131. }
  132. public function allow($mchid,$card_type,$spec) : bool
  133. {
  134. if(!$this->locked($card_type)) {
  135. return true;
  136. }
  137. [$total_lock_type,$spec_lock_type] = $this->merchant_lock_type($mchid,$card_type,$spec);
  138. $merchant = $this->mMerchants[$mchid];
  139. if($spec_lock_type == rlock::ASSIGN) {
  140. return $merchant->spec_total($spec) >= $spec;
  141. }
  142. elseif($spec_lock_type == rlock::RETAIN)
  143. {
  144. //是否已经满足 Spec
  145. $mch_spec_total = $merchant->spec_total($card_type);
  146. if($mch_spec_total >= $spec) return true;
  147. }
  148. else {
  149. //CLOSE情况,其它两种情况优先。
  150. }
  151. if ($total_lock_type == rlock::ASSIGN) {
  152. $mch_total = $merchant->total($card_type);
  153. if($mch_total < $spec) return false;
  154. }
  155. $system = $this->mSystems[$card_type];
  156. $total = $system->total();
  157. $spec_total = $system->spec_total($spec);
  158. $diff_total = $total - $this->lowest_total($mchid,$card_type);
  159. $diff_spec_total = $spec_total - $this->lowest_spec_total($mchid,$card_type,$spec);
  160. return $diff_spec_total >= $spec && $diff_total >= $spec;
  161. }
  162. //return [$toal_lock,$spec_lock]
  163. private function merchant_lock_type($mchid, $card_type, $spec)
  164. {
  165. if(!array_key_exists($mchid,$this->mMerchants)) {
  166. return [rlock::CLOSE,rlock::CLOSE];
  167. }
  168. $merchant = $this->mMerchants[$mchid];
  169. return $merchant->lock_type($card_type, $spec);
  170. }
  171. //需要为锁定的机构保留的最低量
  172. private function lowest_total($mchid,$card_type)
  173. {
  174. $total = 0;
  175. foreach ($this->mMerchants as $merchant)
  176. {
  177. if($mchid != $merchant->mchid()){
  178. $total += $merchant->total($card_type);
  179. }
  180. }
  181. return $total;
  182. }
  183. private function lowest_spec_total($mchid,$card_type,$spec)
  184. {
  185. $total = 0;
  186. foreach ($this->mMerchants as $merchant)
  187. {
  188. if($mchid != $merchant->mchid()){
  189. $total += $merchant->spec_total($card_type,$spec);
  190. }
  191. }
  192. return $total;
  193. }
  194. private function read_sys()
  195. {
  196. $items = rlock::get_sys();
  197. $parser = function ($key,$val)
  198. {
  199. $datas = explode('-',$key);
  200. $len = count($datas);
  201. if($len != 2) return [false,'','',''];
  202. $card_type = intval($datas[0]);
  203. if($datas[1] == 'open') {
  204. return [true,'open',$card_type,boolval($val)];
  205. }
  206. elseif(is_numeric($datas[1])) {
  207. return [true,'card',$card_type,intval($datas[1])];
  208. }
  209. else {
  210. return [false,'','',''];
  211. }
  212. };
  213. $systems = [];
  214. foreach ($items as $key => $val)
  215. {
  216. [$succ,$name,$card_type,$value] = $parser($key,$val);
  217. if($succ)
  218. {
  219. if(array_key_exists($card_type,$systems)) {
  220. $system = $systems[$card_type];
  221. } else {
  222. $system = new system($card_type);
  223. $systems[$card_type] = $system;
  224. }
  225. if($name == 'open') {
  226. $system->set_opened($value);
  227. }
  228. elseif($name == 'card') {
  229. $system->add_amount($value);
  230. }
  231. }
  232. }
  233. foreach ($systems as $system)
  234. {
  235. if($system->opened()) {
  236. $card_type = $system->card_type();
  237. $this->mSystems[$card_type] = $system;
  238. }
  239. }
  240. }
  241. private function read_merchant()
  242. {
  243. $parser = function ($key,$val,&$merchants)
  244. {
  245. $items = explode('-',$key);
  246. $len = count($items);
  247. if($len < 3) return;
  248. $mchid = intval($items[0]);
  249. if(array_key_exists($mchid,$merchants)) {
  250. $merchant = $merchants[$mchid];
  251. } else {
  252. $merchant = new merchant($mchid);
  253. $merchants[$mchid] = $merchant;
  254. }
  255. $card_type = intval($items[1]);
  256. if($len == 3)
  257. {
  258. if($items[2] == 'turn') {
  259. $lock_type = intval($val);
  260. $merchant->set_total_lock($card_type,$lock_type);
  261. }
  262. }
  263. elseif($len == 4)
  264. {
  265. $amount = intval($items[2]);
  266. if($items[3] == 'turn') {
  267. $lock_type = intval($val);
  268. $merchant->set_spec_lock($card_type,$amount,$lock_type);
  269. }
  270. }
  271. };
  272. $merchants = [];
  273. $items = rlock::get_merchant();
  274. foreach ($items as $key => $val) {
  275. $parser($key, $val, $merchants);
  276. }
  277. foreach ($merchants as $merchant)
  278. {
  279. if($merchant->has_lock()) {
  280. $mchid = $merchant->mchid();
  281. $this->mMerchants[$mchid] = $merchant;
  282. }
  283. }
  284. }
  285. }