|
|
@@ -57,7 +57,16 @@ class GenerateKnowledgeExplanationPdfJob implements ShouldQueue
|
|
|
'pdf_url' => $pdfUrl,
|
|
|
'generated_at' => now(),
|
|
|
]);
|
|
|
- $this->syncPaperRecord($record, $pdfUrl);
|
|
|
+
|
|
|
+ $taskSnapshot = $taskManager->getTaskStatus($this->taskId);
|
|
|
+ $taskData = is_array($taskSnapshot) && isset($taskSnapshot['data']) && is_array($taskSnapshot['data'])
|
|
|
+ ? $taskSnapshot['data']
|
|
|
+ : [];
|
|
|
+
|
|
|
+ $examContent = $this->buildKnowledgeExamContent($record, $pdfUrl, $taskData);
|
|
|
+ $this->syncPaperRecord($record, $pdfUrl, $examContent);
|
|
|
+
|
|
|
+ $difficultyCategoryForStats = (int) ($examContent['paper_info']['difficulty_category'] ?? 2);
|
|
|
|
|
|
$taskManager->markTaskCompleted($this->taskId, [
|
|
|
'paper_id' => $this->knowledgeId,
|
|
|
@@ -65,7 +74,12 @@ class GenerateKnowledgeExplanationPdfJob implements ShouldQueue
|
|
|
'pdfs' => [
|
|
|
'all_pdf' => $pdfUrl,
|
|
|
],
|
|
|
- 'exam_content' => $this->buildKnowledgeExamContent($record, $pdfUrl),
|
|
|
+ 'exam_content' => $examContent,
|
|
|
+ 'stats' => [
|
|
|
+ 'difficulty_category' => $difficultyCategoryForStats,
|
|
|
+ 'total_selected' => count($examContent['questions'] ?? []),
|
|
|
+ 'difficulty_distribution_applied' => true,
|
|
|
+ ],
|
|
|
]);
|
|
|
$taskManager->sendCallback($this->taskId);
|
|
|
} catch (\Throwable $e) {
|
|
|
@@ -89,7 +103,7 @@ class GenerateKnowledgeExplanationPdfJob implements ShouldQueue
|
|
|
app(TaskManager::class)->markTaskFailed($this->taskId, $exception->getMessage());
|
|
|
}
|
|
|
|
|
|
- private function syncPaperRecord(KnowledgeExplanation $record, string $pdfUrl): void
|
|
|
+ private function syncPaperRecord(KnowledgeExplanation $record, string $pdfUrl, array $examContent): void
|
|
|
{
|
|
|
$paperId = (string) ($record->knowledge_id ?? '');
|
|
|
if ($paperId === '') {
|
|
|
@@ -101,6 +115,10 @@ class GenerateKnowledgeExplanationPdfJob implements ShouldQueue
|
|
|
$displayCode = $paperId;
|
|
|
}
|
|
|
|
|
|
+ $paperInfo = $examContent['paper_info'] ?? [];
|
|
|
+ $totalQuestions = (int) ($paperInfo['total_questions'] ?? 0);
|
|
|
+ $difficultyCategory = $paperInfo['difficulty_category'] ?? null;
|
|
|
+
|
|
|
Paper::query()->updateOrCreate(
|
|
|
['paper_id' => $paperId],
|
|
|
[
|
|
|
@@ -113,10 +131,12 @@ class GenerateKnowledgeExplanationPdfJob implements ShouldQueue
|
|
|
],
|
|
|
'paper_name' => '知识点讲解_' . $displayCode,
|
|
|
'paper_type' => 22,
|
|
|
- 'total_questions' => 0,
|
|
|
+ 'total_questions' => $totalQuestions,
|
|
|
'total_score' => 100,
|
|
|
'status' => 'completed',
|
|
|
- 'difficulty_category' => null,
|
|
|
+ 'difficulty_category' => $difficultyCategory !== null && $difficultyCategory !== ''
|
|
|
+ ? (string) $difficultyCategory
|
|
|
+ : null,
|
|
|
'exam_pdf_url' => $pdfUrl,
|
|
|
'grading_pdf_url' => null,
|
|
|
'all_pdf_url' => $pdfUrl,
|
|
|
@@ -125,7 +145,7 @@ class GenerateKnowledgeExplanationPdfJob implements ShouldQueue
|
|
|
);
|
|
|
}
|
|
|
|
|
|
- private function buildKnowledgeExamContent(KnowledgeExplanation $record, string $pdfUrl): array
|
|
|
+ private function buildKnowledgeExamContent(KnowledgeExplanation $record, string $pdfUrl, array $taskData = []): array
|
|
|
{
|
|
|
$paperId = (string) ($record->knowledge_id ?? '');
|
|
|
$displayCode = (string) preg_replace('/^(paper_|knowledge_)/', '', $paperId);
|
|
|
@@ -133,6 +153,11 @@ class GenerateKnowledgeExplanationPdfJob implements ShouldQueue
|
|
|
$displayCode = $paperId;
|
|
|
}
|
|
|
$kpCodes = is_array($record->kp_codes) ? array_values($record->kp_codes) : [];
|
|
|
+ $difficultyCategoryRaw = $taskData['difficulty_category'] ?? null;
|
|
|
+ $difficultyCategoryStr = $difficultyCategoryRaw !== null && $difficultyCategoryRaw !== ''
|
|
|
+ ? (string) $difficultyCategoryRaw
|
|
|
+ : '2';
|
|
|
+
|
|
|
$questions = $this->buildKnowledgeQuestions(100);
|
|
|
$knowledgeDistribution = [];
|
|
|
foreach ($kpCodes as $kpCode) {
|
|
|
@@ -146,6 +171,35 @@ class GenerateKnowledgeExplanationPdfJob implements ShouldQueue
|
|
|
$knowledgeDistribution[$kp] = (int) ($knowledgeDistribution[$kp] ?? 0) + 1;
|
|
|
}
|
|
|
|
|
|
+ $typeDistribution = ['choice' => 0, 'fill' => 0, 'answer' => 0];
|
|
|
+ foreach ($questions as $q) {
|
|
|
+ $t = (string) ($q['question_type'] ?? 'answer');
|
|
|
+ if ($t === 'choice') {
|
|
|
+ $typeDistribution['choice']++;
|
|
|
+ } elseif ($t === 'fill') {
|
|
|
+ $typeDistribution['fill']++;
|
|
|
+ } else {
|
|
|
+ $typeDistribution['answer']++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ $difficultyDistribution = [];
|
|
|
+ $difficultySum = 0.0;
|
|
|
+ $difficultyCount = 0;
|
|
|
+ foreach ($questions as $q) {
|
|
|
+ $dl = $q['metadata']['difficulty_label'] ?? '';
|
|
|
+ if ($dl !== '') {
|
|
|
+ $difficultyDistribution[$dl] = ($difficultyDistribution[$dl] ?? 0) + 1;
|
|
|
+ }
|
|
|
+ if (isset($q['difficulty']) && is_numeric($q['difficulty'])) {
|
|
|
+ $difficultySum += (float) $q['difficulty'];
|
|
|
+ $difficultyCount++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ $averageDifficulty = $difficultyCount > 0 ? $difficultySum / $difficultyCount : null;
|
|
|
+ $totalEstimatedTime = count($questions) * 300;
|
|
|
+
|
|
|
return [
|
|
|
'paper_info' => [
|
|
|
'paper_id' => $paperId,
|
|
|
@@ -154,25 +208,21 @@ class GenerateKnowledgeExplanationPdfJob implements ShouldQueue
|
|
|
'teacher_id' => (string) ($record->teacher_id ?? ''),
|
|
|
'total_questions' => count($questions),
|
|
|
'total_score' => 100,
|
|
|
- 'difficulty_category' => null,
|
|
|
+ 'difficulty_category' => $difficultyCategoryStr,
|
|
|
'created_at' => optional($record->created_at)->toISOString(),
|
|
|
'updated_at' => optional($record->updated_at)->toISOString(),
|
|
|
'exam_code' => $displayCode,
|
|
|
- 'grading_code' => null,
|
|
|
+ 'grading_code' => $displayCode,
|
|
|
'paper_id_num' => $displayCode,
|
|
|
],
|
|
|
'questions' => $questions,
|
|
|
'knowledge_points' => $kpCodes,
|
|
|
'statistics' => [
|
|
|
- 'type_distribution' => [
|
|
|
- 'choice' => 0,
|
|
|
- 'fill' => 0,
|
|
|
- 'answer' => count($questions),
|
|
|
- ],
|
|
|
- 'difficulty_distribution' => [],
|
|
|
+ 'type_distribution' => $typeDistribution,
|
|
|
+ 'difficulty_distribution' => $difficultyDistribution,
|
|
|
'knowledge_point_distribution' => $knowledgeDistribution,
|
|
|
- 'average_difficulty' => null,
|
|
|
- 'total_estimated_time' => 0,
|
|
|
+ 'average_difficulty' => $averageDifficulty,
|
|
|
+ 'total_estimated_time' => $totalEstimatedTime,
|
|
|
],
|
|
|
'pdfs' => [
|
|
|
'all_pdf' => $pdfUrl,
|
|
|
@@ -191,26 +241,35 @@ class GenerateKnowledgeExplanationPdfJob implements ShouldQueue
|
|
|
$cases = is_array($point['cases'] ?? null) ? $point['cases'] : [];
|
|
|
foreach ($cases as $case) {
|
|
|
$questionId = (int) ($case['question_id'] ?? 0);
|
|
|
+ $qType = (string) ($case['question_type'] ?? 'answer');
|
|
|
+ $solutionText = (string) ($case['solution'] ?? '');
|
|
|
+ $difficultyVal = isset($case['difficulty']) && is_numeric($case['difficulty']) ? (float) $case['difficulty'] : null;
|
|
|
$questions[] = [
|
|
|
'question_number' => $seq++,
|
|
|
'question_id' => $questionId > 0 ? (string) $questionId : '',
|
|
|
'question_bank_id' => $questionId > 0 ? $questionId : null,
|
|
|
- 'question_type' => (string) ($case['question_type'] ?? 'answer'),
|
|
|
+ 'question_type' => $qType,
|
|
|
'knowledge_point' => $kpCode,
|
|
|
'knowledge_point_name' => $kpName,
|
|
|
- 'difficulty' => isset($case['difficulty']) && is_numeric($case['difficulty']) ? (float) $case['difficulty'] : null,
|
|
|
+ 'difficulty' => $difficultyVal,
|
|
|
'score' => 0,
|
|
|
- 'estimated_time' => null,
|
|
|
+ 'estimated_time' => 300,
|
|
|
'stem' => (string) ($case['stem'] ?? ''),
|
|
|
'options' => is_array($case['options'] ?? null) ? $case['options'] : [],
|
|
|
'correct_answer' => (string) ($case['answer'] ?? ''),
|
|
|
- 'solution' => (string) ($case['solution'] ?? ''),
|
|
|
+ 'solution' => $solutionText,
|
|
|
'metadata' => [
|
|
|
'source_type' => (string) ($case['source_type'] ?? ''),
|
|
|
'source_label' => (string) ($case['source_label'] ?? ''),
|
|
|
'is_wrong_case' => (bool) ($case['is_wrong_case'] ?? false),
|
|
|
'child_kp_code' => $case['child_kp_code'] ?? null,
|
|
|
'child_kp_name' => $case['child_kp_name'] ?? null,
|
|
|
+ 'has_solution' => $solutionText !== '',
|
|
|
+ 'is_choice' => $qType === 'choice',
|
|
|
+ 'is_fill' => $qType === 'fill',
|
|
|
+ 'is_answer' => $qType === 'answer',
|
|
|
+ 'difficulty_label' => $this->difficultyLabelForPayload($difficultyVal),
|
|
|
+ 'question_type_label' => $this->questionTypeLabelForPayload($qType),
|
|
|
],
|
|
|
];
|
|
|
}
|
|
|
@@ -236,4 +295,29 @@ class GenerateKnowledgeExplanationPdfJob implements ShouldQueue
|
|
|
|
|
|
return $questions;
|
|
|
}
|
|
|
+
|
|
|
+ private function questionTypeLabelForPayload(?string $type): string
|
|
|
+ {
|
|
|
+ return match ($type) {
|
|
|
+ 'choice' => '选择题',
|
|
|
+ 'fill' => '填空题',
|
|
|
+ 'answer' => '解答题',
|
|
|
+ default => '未知题型',
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ private function difficultyLabelForPayload(?float $difficulty): string
|
|
|
+ {
|
|
|
+ if ($difficulty === null) {
|
|
|
+ return '未知';
|
|
|
+ }
|
|
|
+ if ($difficulty <= 0.4) {
|
|
|
+ return '基础';
|
|
|
+ }
|
|
|
+ if ($difficulty <= 0.7) {
|
|
|
+ return '中等';
|
|
|
+ }
|
|
|
+
|
|
|
+ return '拔高';
|
|
|
+ }
|
|
|
}
|