| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- <?php
- namespace App\Services;
- use App\Models\Paper;
- use App\Models\PaperQuestion;
- class PaperPayloadService
- {
- public function buildExamContent(Paper $paper): array
- {
- $paper->loadMissing('questions');
- $questions = $paper->questions ?? collect();
- $codes = $this->generatePaperCodes($paper->paper_id);
- return [
- 'paper_info' => [
- 'paper_id' => $paper->paper_id,
- 'paper_name' => $paper->paper_name ?? '',
- 'student_id' => $paper->student_id ?? '',
- 'teacher_id' => $paper->teacher_id ?? '',
- 'total_questions' => $questions->count(),
- 'total_score' => $paper->total_score ?? 0,
- 'difficulty_category' => $paper->difficulty_category ?? '基础',
- 'created_at' => $paper->created_at?->toISOString(),
- 'updated_at' => $paper->updated_at?->toISOString(),
- 'exam_code' => $codes['exam_code'],
- 'grading_code' => $codes['grading_code'],
- 'paper_id_num' => $codes['paper_id_num'],
- ],
- 'questions' => $questions->map(function (PaperQuestion $q) {
- $options = [];
- if ($q->question_type === 'choice') {
- $questionText = $q->question_text ?? '';
- preg_match_all('/([A-D])\s*[\.\、\:]\s*([^A-D]+?)(?=[A-D]\s*[\.\、\:]|$)/u', $questionText, $matches, PREG_SET_ORDER);
- foreach ($matches as $match) {
- $options[] = [
- 'label' => $match[1],
- 'content' => trim($match[2]),
- ];
- }
- }
- return [
- 'question_number' => $q->question_number,
- 'question_id' => $q->question_id,
- 'question_bank_id' => $q->question_bank_id,
- 'question_type' => $q->question_type,
- 'knowledge_point' => $q->knowledge_point,
- 'difficulty' => $q->difficulty,
- 'score' => $q->score,
- 'estimated_time' => $q->estimated_time,
- 'stem' => $q->question_text ?? '',
- 'options' => $options,
- 'correct_answer' => $q->correct_answer ?? '',
- 'solution' => $q->solution ?? '',
- 'student_answer' => $q->student_answer,
- 'is_correct' => $q->is_correct,
- 'score_obtained' => $q->score_obtained,
- 'score_ratio' => $q->score_ratio,
- 'teacher_comment' => $q->teacher_comment,
- 'graded_at' => $q->graded_at?->toISOString(),
- 'graded_by' => $q->graded_by,
- 'metadata' => [
- 'has_solution' => !empty($q->solution),
- 'is_choice' => $q->question_type === 'choice',
- 'is_fill' => $q->question_type === 'fill',
- 'is_answer' => $q->question_type === 'answer',
- 'difficulty_label' => $this->getDifficultyLabel($q->difficulty),
- 'question_type_label' => $this->getQuestionTypeLabel($q->question_type),
- ],
- ];
- })->toArray(),
- 'statistics' => [
- 'type_distribution' => $this->getTypeDistribution($questions),
- 'difficulty_distribution' => $this->getDifficultyDistribution($questions),
- 'knowledge_point_distribution' => $this->getKnowledgePointDistribution($questions),
- 'average_difficulty' => $questions->avg('difficulty'),
- 'total_estimated_time' => $questions->sum('estimated_time'),
- ],
- 'knowledge_points' => $questions->pluck('knowledge_point')->unique()->filter()->values()->toArray(),
- 'skills' => $this->extractSkillsFromQuestions($questions),
- ];
- }
- public function buildPaperApiPayload(Paper $paper): array
- {
- $examContent = $this->buildExamContent($paper);
- $codes = $this->generatePaperCodes($paper->paper_id);
- return [
- 'success' => true,
- 'paper_id' => $paper->paper_id,
- 'status' => 'ready',
- 'exam_code' => $codes['exam_code'],
- 'grading_code' => $codes['grading_code'],
- 'paper_id_num' => $codes['paper_id_num'],
- 'exam_content' => $examContent,
- 'urls' => [
- 'grading_url' => route('filament.admin.auth.intelligent-exam.grading', ['paper_id' => $paper->paper_id]),
- 'student_exam_url' => route('filament.admin.auth.intelligent-exam.pdf', ['paper_id' => $paper->paper_id, 'answer' => 'false']),
- ],
- 'pdfs' => [
- 'exam_paper_pdf' => $paper->exam_pdf_url,
- 'grading_pdf' => $paper->grading_pdf_url,
- ],
- 'stats' => $examContent['statistics'] ?? null,
- 'created_at' => $paper->created_at?->toISOString(),
- 'updated_at' => $paper->updated_at?->toISOString(),
- ];
- }
- public function generatePaperCodes(string $paperId): array
- {
- if (preg_match('/paper_(\d{12})/', $paperId, $matches)) {
- $paperIdNum = $matches[1];
- } else {
- $paperIdNum = preg_replace('/[^0-9]/', '', $paperId);
- $paperIdNum = str_pad(substr($paperIdNum, 0, 12), 12, '0', STR_PAD_LEFT);
- }
- return [
- 'paper_id_num' => $paperIdNum,
- 'exam_code' => '1' . $paperIdNum,
- 'grading_code' => '2' . $paperIdNum,
- ];
- }
- private function getQuestionTypeLabel(?string $type): string
- {
- return match ($type) {
- 'choice' => '选择题',
- 'fill' => '填空题',
- 'answer' => '解答题',
- default => '未知题型',
- };
- }
- private function getDifficultyLabel(?float $difficulty): string
- {
- if ($difficulty === null) {
- return '未知';
- }
- if ($difficulty <= 0.4) {
- return '基础';
- }
- if ($difficulty <= 0.7) {
- return '中等';
- }
- return '拔高';
- }
- private function getTypeDistribution($questions): array
- {
- $distribution = [];
- foreach ($questions as $question) {
- $type = $question->question_type;
- $distribution[$type] = ($distribution[$type] ?? 0) + 1;
- }
- return $distribution;
- }
- private function getDifficultyDistribution($questions): array
- {
- $distribution = [];
- foreach ($questions as $question) {
- $label = $this->getDifficultyLabel($question->difficulty);
- $distribution[$label] = ($distribution[$label] ?? 0) + 1;
- }
- return $distribution;
- }
- private function getKnowledgePointDistribution($questions): array
- {
- $distribution = [];
- foreach ($questions as $question) {
- $kp = $question->knowledge_point;
- if ($kp) {
- $distribution[$kp] = ($distribution[$kp] ?? 0) + 1;
- }
- }
- return $distribution;
- }
- private function extractSkillsFromQuestions($questions): array
- {
- $skills = [];
- foreach ($questions as $question) {
- $solution = $question->solution ?? '';
- if ($solution) {
- $skillKeywords = ['代入法', '配方法', '因式分解', '换元法', '判别式', '求根公式', '韦达定理'];
- foreach ($skillKeywords as $keyword) {
- if (strpos($solution, $keyword) !== false) {
- $skills[] = $keyword;
- }
- }
- }
- $stem = $question->question_text ?? '';
- if ($stem) {
- preg_match_all('/\{([^}]+)\}/', $stem, $matches);
- foreach ($matches[1] as $match) {
- $skillList = array_map('trim', explode(',', $match));
- $skills = array_merge($skills, $skillList);
- }
- }
- }
- return array_unique(array_filter($skills));
- }
- }
|