MysterySeeLLogicTest.php 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. <?php
  2. namespace Tests\Unit\Farm;
  3. use Tests\TestCase;
  4. use App\Module\Farm\Logics\MysterySeeLLogic;
  5. use App\Module\Farm\Models\FarmMysterySeeLandEffect;
  6. use App\Module\Farm\Models\FarmSeedOutput;
  7. use App\Module\Farm\Models\FarmSeed;
  8. use Illuminate\Foundation\Testing\RefreshDatabase;
  9. use Illuminate\Support\Facades\Cache;
  10. class MysterySeeLLogicTest extends TestCase
  11. {
  12. use RefreshDatabase;
  13. protected MysterySeeLLogic $logic;
  14. protected function setUp(): void
  15. {
  16. parent::setUp();
  17. $this->logic = new MysterySeeLLogic();
  18. // 清除缓存
  19. Cache::flush();
  20. }
  21. /**
  22. * 测试概率覆盖值优先级高于修正值
  23. */
  24. public function testProbabilityOverrideVsModifier()
  25. {
  26. // 创建测试种子
  27. $seed = FarmSeed::factory()->create(['id' => 1]);
  28. // 创建基础产出配置
  29. FarmSeedOutput::factory()->create([
  30. 'seed_id' => 1,
  31. 'item_id' => 2,
  32. 'probability' => 10.0000,
  33. 'min_amount' => 1,
  34. 'max_amount' => 5,
  35. 'is_default' => false
  36. ]);
  37. // 创建测试数据:同时设置修正值和覆盖值
  38. FarmMysterySeeLandEffect::factory()->create([
  39. 'seed_id' => 1,
  40. 'land_type_id' => 6,
  41. 'output_item_id' => 2,
  42. 'probability_modifier' => 5.0000, // 修正值 +5%
  43. 'probability_override' => 30.0000, // 覆盖值 30%
  44. 'is_active' => true
  45. ]);
  46. $result = $this->logic->calculateAdjustedProbabilities(1, 6);
  47. // 应该使用覆盖值30%,而不是基础概率+修正值
  48. $item2Result = collect($result)->firstWhere('item_id', 2);
  49. $this->assertEquals(30.0000, $item2Result['adjusted_probability']);
  50. $this->assertEquals('override', $item2Result['adjustment_type']);
  51. }
  52. /**
  53. * 测试没有覆盖值时使用修正值
  54. */
  55. public function testProbabilityModifierWhenNoOverride()
  56. {
  57. // 创建测试种子
  58. $seed = FarmSeed::factory()->create(['id' => 1]);
  59. // 创建基础产出配置
  60. FarmSeedOutput::factory()->create([
  61. 'seed_id' => 1,
  62. 'item_id' => 2,
  63. 'probability' => 10.0000,
  64. 'min_amount' => 1,
  65. 'max_amount' => 5,
  66. 'is_default' => false
  67. ]);
  68. // 创建测试数据:只设置修正值
  69. FarmMysterySeeLandEffect::factory()->create([
  70. 'seed_id' => 1,
  71. 'land_type_id' => 2,
  72. 'output_item_id' => 2,
  73. 'probability_modifier' => 5.0000, // 修正值 +5%
  74. 'probability_override' => null, // 无覆盖值
  75. 'is_active' => true
  76. ]);
  77. $result = $this->logic->calculateAdjustedProbabilities(1, 2);
  78. // 应该使用基础概率+修正值
  79. $item2Result = collect($result)->firstWhere('item_id', 2);
  80. $this->assertEquals(15.0000, $item2Result['adjusted_probability']); // 10% + 5%
  81. $this->assertEquals('modifier', $item2Result['adjustment_type']);
  82. }
  83. /**
  84. * 测试概率边界值处理
  85. */
  86. public function testProbabilityBoundaries()
  87. {
  88. // 创建测试种子
  89. $seed = FarmSeed::factory()->create(['id' => 1]);
  90. // 创建基础产出配置
  91. FarmSeedOutput::factory()->create([
  92. 'seed_id' => 1,
  93. 'item_id' => 2,
  94. 'probability' => 5.0000,
  95. 'min_amount' => 1,
  96. 'max_amount' => 5,
  97. 'is_default' => false
  98. ]);
  99. // 测试负值修正导致概率小于0的情况
  100. FarmMysterySeeLandEffect::factory()->create([
  101. 'seed_id' => 1,
  102. 'land_type_id' => 1,
  103. 'output_item_id' => 2,
  104. 'probability_modifier' => -10.0000, // -10%,会导致负值
  105. 'probability_override' => null,
  106. 'is_active' => true
  107. ]);
  108. $result = $this->logic->calculateAdjustedProbabilities(1, 1);
  109. // 概率应该被限制在0以上
  110. $item2Result = collect($result)->firstWhere('item_id', 2);
  111. $this->assertEquals(0.0000, $item2Result['adjusted_probability']);
  112. }
  113. /**
  114. * 测试随机选择逻辑
  115. */
  116. public function testRandomSelection()
  117. {
  118. // 创建测试数据
  119. $outputs = [
  120. [
  121. 'item_id' => 2,
  122. 'min_amount' => 1,
  123. 'max_amount' => 5,
  124. 'adjusted_probability' => 50.0000,
  125. 'is_default' => false
  126. ],
  127. [
  128. 'item_id' => 3,
  129. 'min_amount' => 2,
  130. 'max_amount' => 6,
  131. 'adjusted_probability' => 30.0000,
  132. 'is_default' => true
  133. ],
  134. [
  135. 'item_id' => 4,
  136. 'min_amount' => 3,
  137. 'max_amount' => 7,
  138. 'adjusted_probability' => 20.0000,
  139. 'is_default' => false
  140. ]
  141. ];
  142. // 多次测试随机选择,验证结果在预期范围内
  143. $results = [];
  144. for ($i = 0; $i < 100; $i++) {
  145. $reflection = new \ReflectionClass($this->logic);
  146. $method = $reflection->getMethod('randomSelectOutput');
  147. $method->setAccessible(true);
  148. $result = $method->invoke($this->logic, $outputs);
  149. $results[] = $result['item_id'];
  150. }
  151. // 验证所有结果都在预期的物品ID范围内
  152. $uniqueResults = array_unique($results);
  153. $this->assertContains(2, $uniqueResults);
  154. $this->assertContains(3, $uniqueResults);
  155. $this->assertContains(4, $uniqueResults);
  156. }
  157. /**
  158. * 测试缓存功能
  159. */
  160. public function testCacheFunction()
  161. {
  162. // 创建测试种子
  163. $seed = FarmSeed::factory()->create(['id' => 1]);
  164. // 创建基础产出配置
  165. FarmSeedOutput::factory()->create([
  166. 'seed_id' => 1,
  167. 'item_id' => 2,
  168. 'probability' => 10.0000,
  169. 'min_amount' => 1,
  170. 'max_amount' => 5,
  171. 'is_default' => false
  172. ]);
  173. // 创建土地影响配置
  174. FarmMysterySeeLandEffect::factory()->create([
  175. 'seed_id' => 1,
  176. 'land_type_id' => 1,
  177. 'output_item_id' => 2,
  178. 'probability_modifier' => 5.0000,
  179. 'probability_override' => null,
  180. 'is_active' => true
  181. ]);
  182. // 第一次调用,应该从数据库查询
  183. $result1 = $this->logic->calculateAdjustedProbabilities(1, 1);
  184. // 第二次调用,应该从缓存获取
  185. $result2 = $this->logic->calculateAdjustedProbabilities(1, 1);
  186. // 结果应该相同
  187. $this->assertEquals($result1, $result2);
  188. // 清除缓存
  189. $this->logic->clearCache(1, 1);
  190. // 再次调用,应该重新从数据库查询
  191. $result3 = $this->logic->calculateAdjustedProbabilities(1, 1);
  192. $this->assertEquals($result1, $result3);
  193. }
  194. /**
  195. * 测试默认产出处理
  196. */
  197. public function testDefaultOutputHandling()
  198. {
  199. // 创建测试种子
  200. $seed = FarmSeed::factory()->create([
  201. 'id' => 1,
  202. 'item_id' => 100,
  203. 'min_output' => 1,
  204. 'max_output' => 3
  205. ]);
  206. // 不创建任何产出配置,测试默认处理
  207. $result = $this->logic->calculateAdjustedProbabilities(1, 1);
  208. // 应该返回种子的默认配置
  209. $this->assertCount(1, $result);
  210. $this->assertEquals(100, $result[0]['item_id']);
  211. $this->assertEquals(1, $result[0]['min_amount']);
  212. $this->assertEquals(3, $result[0]['max_amount']);
  213. $this->assertEquals(100, $result[0]['adjusted_probability']);
  214. $this->assertEquals('default', $result[0]['adjustment_type']);
  215. }
  216. /**
  217. * 测试异常处理
  218. */
  219. public function testExceptionHandling()
  220. {
  221. // 测试不存在的种子ID
  222. $this->expectException(\Exception::class);
  223. $this->expectExceptionMessage('种子ID 999 不存在');
  224. $reflection = new \ReflectionClass($this->logic);
  225. $method = $reflection->getMethod('getDefaultOutput');
  226. $method->setAccessible(true);
  227. $method->invoke($this->logic, 999);
  228. }
  229. }