DifficultyDistributionService.php 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. <?php
  2. namespace App\Services;
  3. class DifficultyDistributionService
  4. {
  5. public function calculateDistribution(int $category, int $totalQuestions): array
  6. {
  7. switch ($category) {
  8. case 0:
  9. $mediumPercentage = 90; // 0-0.1
  10. $lowPercentage = 0;
  11. $highPercentage = 10; // 0.1-0.25
  12. break;
  13. case 1:
  14. $mediumPercentage = 90; // 0-0.25
  15. $lowPercentage = 0;
  16. $highPercentage = 10;
  17. break;
  18. case 2:
  19. $mediumPercentage = 50; // 0.25-0.5
  20. $lowPercentage = 25; // <0.25
  21. $highPercentage = 25; // >0.5
  22. break;
  23. case 3:
  24. $mediumPercentage = 50; // 0.5-0.75
  25. $lowPercentage = 25; // <0.5
  26. $highPercentage = 25; // >0.75
  27. break;
  28. case 4:
  29. $mediumPercentage = 50; // 0.75-1
  30. $lowPercentage = 25; // <0.75
  31. $highPercentage = 25; // >0.75
  32. break;
  33. default:
  34. $lowPercentage = 25;
  35. $mediumPercentage = 50;
  36. $highPercentage = 25;
  37. }
  38. $lowCount = (int) round($totalQuestions * $lowPercentage / 100);
  39. $mediumCount = (int) round($totalQuestions * $mediumPercentage / 100);
  40. $highCount = $totalQuestions - $lowCount - $mediumCount;
  41. return [
  42. 'low' => [
  43. 'percentage' => $lowPercentage,
  44. 'count' => $lowCount,
  45. 'label' => '低级难度'
  46. ],
  47. 'medium' => [
  48. 'percentage' => $mediumPercentage,
  49. 'count' => $mediumCount,
  50. 'label' => '基准难度'
  51. ],
  52. 'high' => [
  53. 'percentage' => $highPercentage,
  54. 'count' => $highCount,
  55. 'label' => '拔高难度'
  56. ]
  57. ];
  58. }
  59. public function getRanges(int $category): array
  60. {
  61. switch ($category) {
  62. case 0:
  63. return [
  64. 'primary' => ['min' => 0.0, 'max' => 0.1, 'percentage' => 90],
  65. 'secondary' => ['min' => 0.1, 'max' => 0.25, 'percentage' => 10],
  66. 'description' => '0基础型:0-0.1占比90%,0.1-0.25占比10%'
  67. ];
  68. case 1:
  69. return [
  70. 'primary' => ['min' => 0.0, 'max' => 0.25, 'percentage' => 90],
  71. 'secondary' => ['min' => 0.25, 'max' => 1.0, 'percentage' => 10],
  72. 'description' => '基础型:0-0.25占比90%,0.25-1占比10%'
  73. ];
  74. case 2:
  75. return [
  76. 'primary' => ['min' => 0.25, 'max' => 0.5, 'percentage' => 50],
  77. 'low' => ['min' => 0.0, 'max' => 0.25, 'percentage' => 25],
  78. 'high' => ['min' => 0.5, 'max' => 1.0, 'percentage' => 25],
  79. 'description' => '进阶型:0.25-0.5占比50%,<0.25占比25%,>0.5占比25%'
  80. ];
  81. case 3:
  82. return [
  83. 'primary' => ['min' => 0.5, 'max' => 0.75, 'percentage' => 50],
  84. 'low' => ['min' => 0.0, 'max' => 0.5, 'percentage' => 25],
  85. 'high' => ['min' => 0.75, 'max' => 1.0, 'percentage' => 25],
  86. 'description' => '中等型:0.5-0.75占比50%,<0.5占比25%,>0.75占比25%'
  87. ];
  88. case 4:
  89. return [
  90. 'primary' => ['min' => 0.75, 'max' => 1.0, 'percentage' => 50],
  91. 'secondary' => ['min' => 0.0, 'max' => 0.75, 'percentage' => 50],
  92. 'description' => '拔高型:0.75-1占比50%,其他占比50%'
  93. ];
  94. default:
  95. return [
  96. 'primary' => ['min' => 0.0, 'max' => 1.0, 'percentage' => 100],
  97. 'description' => '默认:全难度范围'
  98. ];
  99. }
  100. }
  101. public function groupQuestionsByDifficultyRange(array $questions, int $category): array
  102. {
  103. $buckets = [
  104. 'primary_low' => [],
  105. 'primary_medium' => [],
  106. 'primary_high' => [],
  107. 'secondary' => [],
  108. 'other' => []
  109. ];
  110. foreach ($questions as $question) {
  111. $difficulty = (float) ($question['difficulty'] ?? 0);
  112. $rangeKey = $this->classifyQuestionByDifficulty($difficulty, $category);
  113. $buckets[$rangeKey][] = $question;
  114. }
  115. return $buckets;
  116. }
  117. public function classifyQuestionByDifficulty(float $difficulty, int $category): string
  118. {
  119. switch ($category) {
  120. case 0:
  121. if ($difficulty >= 0 && $difficulty <= 0.1) {
  122. return 'primary_medium';
  123. }
  124. if ($difficulty > 0.1 && $difficulty <= 0.25) {
  125. return 'secondary';
  126. }
  127. return 'other';
  128. case 1:
  129. if ($difficulty >= 0 && $difficulty <= 0.25) {
  130. return 'primary_medium';
  131. }
  132. return 'secondary';
  133. case 2:
  134. if ($difficulty >= 0.25 && $difficulty <= 0.5) {
  135. return 'primary_medium';
  136. }
  137. if ($difficulty < 0.25) {
  138. return 'primary_low';
  139. }
  140. return 'primary_high';
  141. case 3:
  142. if ($difficulty >= 0.5 && $difficulty <= 0.75) {
  143. return 'primary_medium';
  144. }
  145. if ($difficulty < 0.5) {
  146. return 'primary_low';
  147. }
  148. return 'primary_high';
  149. case 4:
  150. if ($difficulty >= 0.75 && $difficulty <= 1.0) {
  151. return 'primary_medium';
  152. }
  153. return 'secondary';
  154. default:
  155. return 'other';
  156. }
  157. }
  158. public function mapDifficultyLevelToRangeKey(string $level, int $category): string
  159. {
  160. switch ($category) {
  161. case 0:
  162. return match($level) {
  163. 'low' => 'secondary',
  164. 'medium' => 'primary_medium',
  165. 'high' => 'secondary',
  166. default => 'secondary'
  167. };
  168. case 1:
  169. return match($level) {
  170. 'low' => 'secondary',
  171. 'medium' => 'primary_medium',
  172. 'high' => 'secondary',
  173. default => 'secondary'
  174. };
  175. case 2:
  176. return match($level) {
  177. 'low' => 'primary_low',
  178. 'medium' => 'primary_medium',
  179. 'high' => 'primary_high',
  180. default => 'other'
  181. };
  182. case 3:
  183. return match($level) {
  184. 'low' => 'primary_low',
  185. 'medium' => 'primary_medium',
  186. 'high' => 'primary_high',
  187. default => 'other'
  188. };
  189. case 4:
  190. return match($level) {
  191. 'low' => 'secondary',
  192. 'medium' => 'primary_medium',
  193. 'high' => 'secondary',
  194. default => 'secondary'
  195. };
  196. default:
  197. return 'other';
  198. }
  199. }
  200. public function getSupplementOrder(int $category): array
  201. {
  202. return match ($category) {
  203. 0, 1, 4 => ['secondary', 'other'],
  204. 2, 3 => ['primary_medium', 'primary_low', 'primary_high', 'other'],
  205. default => ['other']
  206. };
  207. }
  208. }