ItemOutputLimit.php 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. <?php
  2. namespace App\Module\GameItems\Models;
  3. use Illuminate\Database\Eloquent\Relations\BelongsTo;
  4. use Illuminate\Database\Eloquent\Relations\HasMany;
  5. use UCore\ModelCore;
  6. /**
  7. * 物品产出限制
  8. *
  9. * field start
  10. * @property int $id 记录ID,主键
  11. * @property int $item_id 物品ID,外键关联kku_item_items表
  12. * @property int $limit_type 限制类型(1:全局总量, 2:单个用户, 3:单日全局, 4:单日用户)
  13. * @property int $max_quantity 最大产出数量
  14. * @property int $current_quantity 当前已产出数量(全局限制时使用)
  15. * @property int $reset_type 重置类型(0:不重置, 1:每日, 2:每周, 3:每月)
  16. * @property string $last_reset_time 上次重置时间
  17. * @property object|array $related_items 关联物品ID列表,这些物品共享同一个限制额度
  18. * @property \Carbon\Carbon $created_at 创建时间
  19. * @property \Carbon\Carbon $updated_at 更新时间
  20. * field end
  21. */
  22. class ItemOutputLimit extends ModelCore
  23. {
  24. /**
  25. * 与模型关联的表名
  26. *
  27. * @var string
  28. */
  29. protected $table = 'item_output_limits';
  30. // attrlist start
  31. protected $fillable = [
  32. 'id',
  33. 'item_id',
  34. 'limit_type',
  35. 'max_quantity',
  36. 'current_quantity',
  37. 'reset_type',
  38. 'last_reset_time',
  39. 'related_items',
  40. ];
  41. // attrlist end
  42. /**
  43. * 可批量赋值的属性
  44. *
  45. * @var array
  46. */
  47. protected $fillable = [
  48. 'item_id',
  49. 'limit_type',
  50. 'max_quantity',
  51. 'period_type',
  52. 'period_value',
  53. 'reset_time',
  54. 'is_active',
  55. ];
  56. /**
  57. * 应该被转换为日期的属性
  58. *
  59. * @var array
  60. */
  61. protected $dates = [
  62. 'reset_time',
  63. 'created_at',
  64. 'updated_at',
  65. ];
  66. /**
  67. * 应该被转换为原生类型的属性
  68. *
  69. * @var array
  70. */
  71. protected $casts = [
  72. 'max_quantity' => 'integer',
  73. 'period_type' => 'integer',
  74. 'period_value' => 'integer',
  75. 'is_active' => 'boolean',
  76. ];
  77. /**
  78. * 限制类型常量
  79. */
  80. const LIMIT_TYPE_GLOBAL = 1; // 全局限制
  81. const LIMIT_TYPE_USER = 2; // 用户限制
  82. const LIMIT_TYPE_DAILY = 3; // 每日限制
  83. const LIMIT_TYPE_WEEKLY = 4; // 每周限制
  84. const LIMIT_TYPE_MONTHLY = 5; // 每月限制
  85. /**
  86. * 获取关联的物品
  87. *
  88. * @return BelongsTo
  89. */
  90. public function item(): BelongsTo
  91. {
  92. return $this->belongsTo(ItemItem::class, 'item_id');
  93. }
  94. /**
  95. * 获取用户产出限制计数
  96. *
  97. * @return HasMany
  98. */
  99. public function userCounters(): HasMany
  100. {
  101. return $this->hasMany(ItemUserOutputCounter::class, 'limit_id');
  102. }
  103. /**
  104. * 检查是否达到全局限制
  105. *
  106. * @return bool
  107. */
  108. public function isGlobalLimitReached(): bool
  109. {
  110. if ($this->limit_type != self::LIMIT_TYPE_GLOBAL) {
  111. return false;
  112. }
  113. $totalCount = ItemUserOutputCounter::where('limit_id', $this->id)
  114. ->sum('current_count');
  115. return $totalCount >= $this->max_quantity;
  116. }
  117. /**
  118. * 检查用户是否达到限制
  119. *
  120. * @param int $userId 用户ID
  121. * @return bool
  122. */
  123. public function isUserLimitReached(int $userId): bool
  124. {
  125. if ($this->limit_type == self::LIMIT_TYPE_GLOBAL) {
  126. return $this->isGlobalLimitReached();
  127. }
  128. $counter = ItemUserOutputCounter::where('limit_id', $this->id)
  129. ->where('user_id', $userId)
  130. ->first();
  131. if (!$counter) {
  132. return false;
  133. }
  134. return $counter->current_count >= $this->max_quantity;
  135. }
  136. /**
  137. * 增加计数
  138. *
  139. * @param int $userId 用户ID
  140. * @param int $count 增加的数量
  141. * @return bool
  142. */
  143. public function incrementCount(int $userId, int $count = 1): bool
  144. {
  145. $counter = ItemUserOutputCounter::firstOrCreate(
  146. [
  147. 'limit_id' => $this->id,
  148. 'user_id' => $userId,
  149. ],
  150. [
  151. 'current_count' => 0,
  152. 'last_reset_time' => now(),
  153. ]
  154. );
  155. // 检查是否需要重置计数
  156. if ($this->shouldResetCounter($counter)) {
  157. $counter->current_count = 0;
  158. $counter->last_reset_time = now();
  159. }
  160. $counter->current_count += $count;
  161. return $counter->save();
  162. }
  163. /**
  164. * 检查是否应该重置计数器
  165. *
  166. * @param ItemUserOutputCounter $counter 计数器
  167. * @return bool
  168. */
  169. protected function shouldResetCounter(ItemUserOutputCounter $counter): bool
  170. {
  171. if (empty($counter->last_reset_time)) {
  172. return true;
  173. }
  174. switch ($this->limit_type) {
  175. case self::LIMIT_TYPE_DAILY:
  176. return $counter->last_reset_time->diffInDays(now()) >= 1;
  177. case self::LIMIT_TYPE_WEEKLY:
  178. return $counter->last_reset_time->diffInWeeks(now()) >= 1;
  179. case self::LIMIT_TYPE_MONTHLY:
  180. return $counter->last_reset_time->diffInMonths(now()) >= 1;
  181. default:
  182. return false;
  183. }
  184. }
  185. }