Tree.php 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. <?php
  2. namespace app\models\tree;
  3. use crmeb\basic\BaseModel;
  4. use crmeb\traits\ModelTrait;
  5. use think\db\exception\DataNotFoundException;
  6. use think\db\exception\DbException;
  7. use think\db\exception\ModelNotFoundException;
  8. class Tree extends BaseModel
  9. {
  10. /**
  11. * 数据表主键
  12. * @var string
  13. */
  14. protected $pk = 'id';
  15. /**
  16. * 模型名称
  17. * @var string
  18. */
  19. protected $name = 'tree';
  20. use ModelTrait;
  21. /**
  22. * 排点
  23. * @param int $uid
  24. * @param int $spread_uid
  25. * @return array|bool|int[]
  26. * @throws DataNotFoundException
  27. * @throws DbException
  28. * @throws ModelNotFoundException
  29. */
  30. public static function getTreePoint(int $uid, int $spread_uid = 0)
  31. {
  32. if (!self::count()) {
  33. return [1, 1];
  34. }
  35. if (self::where('uid', $uid)->order('add_time', 'asc')->where('status', 0)->find()) {
  36. return self::setErrorInfo('尚未出局,不可复投');
  37. }
  38. $tree_leader = 1;
  39. $spread_last_point = self::where('uid', $spread_uid)->where('status', 0)->find();
  40. while ($spread_last_point) {
  41. $tree_leader = $spread_last_point['tree_num'];
  42. $spread_last_point = self::where('tree_num', floor($spread_last_point['tree_num'] / 2))->where('status', 0)->find();
  43. }
  44. $gp_point = 1;
  45. $gp_point_list = [$tree_leader * 2, $tree_leader * 2 + 1];
  46. while (1) {
  47. $member_list = self::where('tree_num', 'in', $gp_point_list)->order('tree_num', 'asc')->select();
  48. if (count($member_list) < count($gp_point_list)) {
  49. foreach ($gp_point_list as $k => $v) {
  50. if (!isset($member_list[$k]) || $v != $member_list[$k]['tree_num']) {
  51. $gp_point = $v;
  52. break;
  53. }
  54. }
  55. break;
  56. }
  57. $gp_point_list = [];
  58. foreach ($member_list as $v) {
  59. $gp_point_list[] = $v['tree_num'] * 2;
  60. $gp_point_list[] = $v['tree_num'] * 2 + 1;
  61. }
  62. }
  63. return [$gp_point, $tree_leader];
  64. }
  65. /**
  66. * 进场
  67. * @param int $uid
  68. * @param int $spread_uid
  69. * @return bool
  70. * @throws DataNotFoundException
  71. * @throws DbException
  72. * @throws ModelNotFoundException
  73. */
  74. public static function insertTree(int $uid, int $spread_uid = 0): bool
  75. {
  76. $res = self::getTreePoint($uid, $spread_uid);
  77. if (!$res) return self::setErrorInfo(self::getErrorInfo());
  78. list($point, $tree_leader) = $res;
  79. self::beginTrans();
  80. try {
  81. $res = self::create([
  82. 'uid' => $uid,
  83. 'tree_num' => $point,
  84. 'add_time' => time(),
  85. ]);
  86. $res = $res && self::sendToUper($point);
  87. $gp_point_list = [$tree_leader * 2, $tree_leader * 2 + 1];
  88. $gp_point_all = $gp_point_list;
  89. $i = 9;
  90. while (--$i) {
  91. $set = [];
  92. foreach ($gp_point_list as $v) {
  93. $gp_point_all[] = $v * 2;
  94. $gp_point_all[] = $v * 2 + 1;
  95. $set[] = $v * 2;
  96. $set[] = $v * 2 + 1;
  97. }
  98. $gp_point_list = $set;
  99. }
  100. if (count($gp_point_all) == self::where('tree_num', 'in', $gp_point_all)->count()) {
  101. //出局
  102. $info = self::where('tree_num', $tree_leader)->find();
  103. $info->status = 1;
  104. $res = $res && $info->save();
  105. }
  106. self::checkTrans($res);
  107. if ($res) {
  108. return true;
  109. } else {
  110. return self::setErrorInfo('加入失败');
  111. }
  112. } catch (\Exception $e) {
  113. self::rollbackTrans();
  114. return self::setErrorInfo($e->getMessage());
  115. }
  116. }
  117. /**
  118. * 发奖
  119. * @param int $point
  120. * @return bool
  121. * @throws DataNotFoundException
  122. * @throws DbException
  123. * @throws ModelNotFoundException
  124. */
  125. public static function sendToUper(int $point): bool
  126. {
  127. $up_point = floor($point / 2);
  128. $info = self::where('tree_num', $up_point)->find();
  129. $res = true;
  130. while ($info) {
  131. $info->get += 140;
  132. $res = $res && $info->save();
  133. $up_point = floor($up_point / 2);
  134. $info = self::where('tree_num', $up_point)->where('status', 0)->find();
  135. }
  136. return $res;
  137. }
  138. }