|
|
@@ -30,7 +30,7 @@ class ExamTypeStrategy
|
|
|
|
|
|
/**
|
|
|
* 根据组卷类型构建参数
|
|
|
- * assembleType: 0-新摸底, 1-智能组卷, 2-知识点组卷, 3-教材组卷, 4-通用, 5-错题本, 9-原摸底
|
|
|
+ * assembleType: 0-新摸底, 8-智能组卷, 2-知识点组卷, 3-教材组卷, 4-通用, 5-错题本, 9-原摸底
|
|
|
*/
|
|
|
public function buildParams(array $baseParams, int $assembleType): array
|
|
|
{
|
|
|
@@ -41,11 +41,12 @@ class ExamTypeStrategy
|
|
|
|
|
|
return match($assembleType) {
|
|
|
0 => $this->applyDifficultyDistribution($this->buildInitialDiagnosticParams($baseParams)), // 新摸底
|
|
|
- 1 => $this->applyDifficultyDistribution($this->buildIntelligentAssembleParams($baseParams)), // 智能组卷
|
|
|
+ 1 => $this->applyDifficultyDistribution($this->buildIntelligentAssembleParams($baseParams)), // 智能组卷(旧参数兼容)
|
|
|
2 => $this->applyDifficultyDistribution($this->buildKnowledgePointAssembleParams($baseParams)), // 知识点组卷
|
|
|
3 => $this->applyDifficultyDistribution($this->buildTextbookAssembleParams($baseParams)), // 教材组卷
|
|
|
4 => $this->applyDifficultyDistribution($this->buildGeneralParams($baseParams)), // 通用
|
|
|
5 => $this->applyDifficultyDistribution($this->buildMistakeParams($baseParams)), // 追练
|
|
|
+ 8 => $this->applyDifficultyDistribution($this->buildIntelligentAssembleParams($baseParams)), // 智能组卷
|
|
|
9 => $this->applyDifficultyDistribution($this->buildDiagnosticParams($baseParams)), // 原摸底
|
|
|
default => $this->applyDifficultyDistribution($this->buildGeneralParams($baseParams))
|
|
|
};
|
|
|
@@ -729,9 +730,8 @@ class ExamTypeStrategy
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 智能组卷 (assembleType=1)
|
|
|
- * 根据 textbook_id 查询章节,获取知识点,然后组卷
|
|
|
- * 增加年级概念选题逻辑
|
|
|
+ * 智能组卷 (assembleType=8, 兼容旧 assembleType=1)
|
|
|
+ * 基于教材知识点顺序与学生掌握度,选择首个未达标知识点(或其列表)组卷
|
|
|
*/
|
|
|
private function buildIntelligentAssembleParams(array $params): array
|
|
|
{
|
|
|
@@ -740,47 +740,71 @@ class ExamTypeStrategy
|
|
|
$textbookId = $params['textbook_id'] ?? null;
|
|
|
$grade = $params['grade'] ?? null; // 年级信息
|
|
|
$totalQuestions = $params['total_questions'] ?? 20;
|
|
|
+ $studentId = (int) ($params['student_id'] ?? 0);
|
|
|
|
|
|
if (!$textbookId) {
|
|
|
Log::warning('ExamTypeStrategy: 智能组卷需要 textbook_id 参数');
|
|
|
return $this->buildGeneralParams($params);
|
|
|
}
|
|
|
|
|
|
- // 第一步:根据 textbook_id 查询章节
|
|
|
- $catalogChapterIds = $this->getTextbookChapterIds($textbookId);
|
|
|
+ $diagnosticService = app(DiagnosticChapterService::class);
|
|
|
+ $textbookKpCodes = $diagnosticService->getTextbookKnowledgePointsInOrder((int) $textbookId);
|
|
|
|
|
|
- if (empty($catalogChapterIds)) {
|
|
|
- Log::warning('ExamTypeStrategy: 未找到课本章节', ['textbook_id' => $textbookId]);
|
|
|
+ if (empty($textbookKpCodes)) {
|
|
|
+ Log::warning('ExamTypeStrategy: 教材未找到知识点', ['textbook_id' => $textbookId]);
|
|
|
return $this->buildGeneralParams($params);
|
|
|
}
|
|
|
|
|
|
- Log::info('ExamTypeStrategy: 获取到课本章节', [
|
|
|
- 'textbook_id' => $textbookId,
|
|
|
- 'chapter_count' => count($catalogChapterIds)
|
|
|
- ]);
|
|
|
+ $masteryMap = [];
|
|
|
+ if ($studentId) {
|
|
|
+ $masteryMap = StudentKnowledgeMastery::query()
|
|
|
+ ->where('student_id', $studentId)
|
|
|
+ ->whereIn('kp_code', $textbookKpCodes)
|
|
|
+ ->pluck('mastery_level', 'kp_code')
|
|
|
+ ->toArray();
|
|
|
+ }
|
|
|
|
|
|
- // 第二步:根据章节ID查询知识点关联
|
|
|
- $kpCodes = $this->getKnowledgePointsFromChapters($catalogChapterIds, 25);
|
|
|
+ $matchedKpCodes = array_values(array_intersect($textbookKpCodes, array_keys($masteryMap)));
|
|
|
|
|
|
- if (empty($kpCodes)) {
|
|
|
- Log::warning('ExamTypeStrategy: 未找到知识点关联', [
|
|
|
- 'textbook_id' => $textbookId,
|
|
|
- 'chapter_ids' => $catalogChapterIds
|
|
|
- ]);
|
|
|
- return $this->buildGeneralParams($params);
|
|
|
+ if (empty($matchedKpCodes)) {
|
|
|
+ $initial = $diagnosticService->getInitialChapterKnowledgePoints((int) $textbookId);
|
|
|
+ $kpCodes = $initial['kp_codes'] ?? [];
|
|
|
+
|
|
|
+ if (empty($kpCodes)) {
|
|
|
+ Log::warning('ExamTypeStrategy: 智能组卷未找到首章知识点', [
|
|
|
+ 'textbook_id' => $textbookId
|
|
|
+ ]);
|
|
|
+ return $this->buildGeneralParams($params);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ $kpCodes = [];
|
|
|
+ foreach ($textbookKpCodes as $kpCode) {
|
|
|
+ if (!isset($masteryMap[$kpCode])) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ $level = (float) $masteryMap[$kpCode];
|
|
|
+ if ($level < 0.9) {
|
|
|
+ $kpCodes[] = $kpCode;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (empty($kpCodes)) {
|
|
|
+ $initial = $diagnosticService->getInitialChapterKnowledgePoints((int) $textbookId);
|
|
|
+ $kpCodes = $initial['kp_codes'] ?? [];
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
Log::info('ExamTypeStrategy: 获取到知识点', [
|
|
|
'kp_count' => count($kpCodes),
|
|
|
- 'kp_codes' => array_slice($kpCodes, 0, 5) // 只记录前5个
|
|
|
+ 'kp_codes' => array_slice($kpCodes, 0, 5)
|
|
|
]);
|
|
|
|
|
|
// 组装增强参数
|
|
|
$enhanced = array_merge($params, [
|
|
|
- 'kp_codes' => $kpCodes,
|
|
|
+ 'kp_code_list' => $kpCodes,
|
|
|
'textbook_id' => $textbookId,
|
|
|
'grade' => $grade,
|
|
|
- 'catalog_chapter_ids' => $catalogChapterIds,
|
|
|
'paper_name' => $params['paper_name'] ?? ('智能组卷_' . now()->format('Ymd_His')),
|
|
|
// 智能组卷:平衡的题型和难度配比
|
|
|
'question_type_ratio' => [
|
|
|
@@ -804,7 +828,7 @@ class ExamTypeStrategy
|
|
|
'total_questions' => $totalQuestions
|
|
|
]);
|
|
|
|
|
|
- return $enhanced;
|
|
|
+ return $this->buildKnowledgePointAssembleParams($enhanced);
|
|
|
}
|
|
|
|
|
|
/**
|