DiagnosticChapterService.php 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. <?php
  2. namespace App\Services;
  3. use Illuminate\Support\Facades\Log;
  4. use App\Models\KnowledgePoint;
  5. use App\Models\StudentKnowledgeMastery;
  6. use App\Models\TextbookCatalog;
  7. use App\Models\TextbookChapterKnowledgeRelation;
  8. class DiagnosticChapterService
  9. {
  10. public function getInitialChapterKnowledgePoints(int $textbookId): array
  11. {
  12. $chapter = TextbookCatalog::query()
  13. ->where('textbook_id', $textbookId)
  14. ->where('node_type', 'chapter')
  15. ->orderBy('display_no')
  16. ->orderBy('sort_order')
  17. ->orderBy('id')
  18. ->first();
  19. if (!$chapter) {
  20. Log::warning('DiagnosticChapterService: 未找到章节节点', [
  21. 'textbook_id' => $textbookId,
  22. ]);
  23. return [];
  24. }
  25. $sectionIds = TextbookCatalog::query()
  26. ->where('parent_id', $chapter->id)
  27. ->where('node_type', 'section')
  28. ->orderBy('display_no')
  29. ->orderBy('sort_order')
  30. ->orderBy('id')
  31. ->pluck('id')
  32. ->toArray();
  33. if (empty($sectionIds)) {
  34. Log::warning('DiagnosticChapterService: 章节下未找到section节点', [
  35. 'textbook_id' => $textbookId,
  36. 'chapter_id' => $chapter->id,
  37. ]);
  38. return [];
  39. }
  40. $kpCodes = TextbookChapterKnowledgeRelation::query()
  41. ->whereIn('catalog_chapter_id', $sectionIds)
  42. ->pluck('kp_code')
  43. ->filter()
  44. ->unique()
  45. ->values()
  46. ->toArray();
  47. $kpCodes = $this->expandWithChildKnowledgePoints($kpCodes);
  48. Log::info('DiagnosticChapterService: 获取首章知识点', [
  49. 'textbook_id' => $textbookId,
  50. 'chapter_id' => $chapter->id,
  51. 'section_count' => count($sectionIds),
  52. 'kp_count' => count($kpCodes),
  53. ]);
  54. return [
  55. 'chapter_id' => $chapter->id,
  56. 'section_ids' => $sectionIds,
  57. 'kp_codes' => $kpCodes,
  58. ];
  59. }
  60. public function getFirstUnmasteredChapterKnowledgePoints(int $textbookId, int $studentId, float $threshold = 0.9): array
  61. {
  62. $chapters = TextbookCatalog::query()
  63. ->where('textbook_id', $textbookId)
  64. ->where('node_type', 'chapter')
  65. ->orderBy('display_no')
  66. ->orderBy('sort_order')
  67. ->orderBy('id')
  68. ->get();
  69. if ($chapters->isEmpty()) {
  70. Log::warning('DiagnosticChapterService: 未找到章节节点', [
  71. 'textbook_id' => $textbookId,
  72. ]);
  73. return [];
  74. }
  75. foreach ($chapters as $chapter) {
  76. $sectionIds = TextbookCatalog::query()
  77. ->where('parent_id', $chapter->id)
  78. ->where('node_type', 'section')
  79. ->orderBy('display_no')
  80. ->orderBy('sort_order')
  81. ->orderBy('id')
  82. ->pluck('id')
  83. ->toArray();
  84. if (empty($sectionIds)) {
  85. continue;
  86. }
  87. $kpCodes = TextbookChapterKnowledgeRelation::query()
  88. ->whereIn('catalog_chapter_id', $sectionIds)
  89. ->pluck('kp_code')
  90. ->filter()
  91. ->unique()
  92. ->values()
  93. ->toArray();
  94. $kpCodes = $this->expandWithChildKnowledgePoints($kpCodes);
  95. if (empty($kpCodes)) {
  96. continue;
  97. }
  98. $allMastered = StudentKnowledgeMastery::allAtLeast($studentId, $kpCodes, $threshold);
  99. Log::info('DiagnosticChapterService: 章节掌握度评估', [
  100. 'student_id' => $studentId,
  101. 'textbook_id' => $textbookId,
  102. 'chapter_id' => $chapter->id,
  103. 'section_count' => count($sectionIds),
  104. 'kp_count' => count($kpCodes),
  105. 'all_mastered' => $allMastered,
  106. 'threshold' => $threshold,
  107. ]);
  108. if (!$allMastered) {
  109. return [
  110. 'chapter_id' => $chapter->id,
  111. 'section_ids' => $sectionIds,
  112. 'kp_codes' => $kpCodes,
  113. 'all_mastered' => $allMastered,
  114. ];
  115. }
  116. }
  117. Log::info('DiagnosticChapterService: 所有章节均达到掌握度阈值', [
  118. 'student_id' => $studentId,
  119. 'textbook_id' => $textbookId,
  120. 'threshold' => $threshold,
  121. ]);
  122. return [];
  123. }
  124. private function expandWithChildKnowledgePoints(array $kpCodes): array
  125. {
  126. if (empty($kpCodes)) {
  127. return [];
  128. }
  129. $baseCodes = collect($kpCodes)->filter()->unique()->values()->all();
  130. $children = KnowledgePoint::query()
  131. ->whereIn('parent_kp_code', $baseCodes)
  132. ->pluck('kp_code')
  133. ->filter()
  134. ->unique()
  135. ->values()
  136. ->toArray();
  137. return array_values(array_unique(array_merge($baseCodes, $children)));
  138. }
  139. }