| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 |
- <?php
- namespace App\Services;
- use App\Models\Question;
- class QuestionPayloadMapper
- {
- /**
- * @param array<int, string> $fallbackKpCodes
- * @return array<string, mixed>
- */
- public function fromArray(array $question, array $fallbackKpCodes = []): array
- {
- $type = $this->normalizeQuestionType(
- (string) ($question['question_type'] ?? $question['type'] ?? '')
- ) ?? $this->guessType($question);
- $kpCode = (string) ($question['kp_code']
- ?? $question['kp']
- ?? $question['knowledge_point']
- ?? $question['knowledge_point_code']
- ?? ($fallbackKpCodes[0] ?? ''));
- $id = $question['id'] ?? $question['question_id'] ?? $question['question_bank_id'] ?? null;
- return [
- 'id' => $id,
- 'question_id' => $question['question_id'] ?? $id,
- 'question_type' => $type,
- 'stem' => $question['stem'] ?? $question['content'] ?? ($question['question_text'] ?? ''),
- 'content' => $question['content'] ?? $question['stem'] ?? '',
- 'options' => $question['options'] ?? ($question['choices'] ?? []),
- 'answer' => $question['answer'] ?? $question['correct_answer'] ?? '',
- 'solution' => $question['solution'] ?? '',
- 'difficulty' => $this->normalizeDifficulty($question['difficulty'] ?? null),
- 'score' => $question['score'] ?? $this->defaultScore($type),
- 'estimated_time' => $question['estimated_time'] ?? 300,
- 'kp' => $kpCode,
- 'kp_code' => $kpCode,
- ];
- }
- /**
- * @return array<string, mixed>
- */
- public function fromModel(Question $question): array
- {
- return $this->fromArray([
- 'id' => $question->id,
- 'question_id' => $question->id,
- 'question_type' => $question->question_type,
- 'stem' => $question->stem,
- 'content' => $question->stem,
- 'options' => $question->options ?? [],
- 'answer' => $question->answer,
- 'solution' => $question->solution,
- 'difficulty' => $question->difficulty,
- 'kp_code' => $question->kp_code,
- ]);
- }
- public function normalizeQuestionType(?string $type): ?string
- {
- $type = strtolower(trim((string) $type));
- if (in_array($type, ['choice', 'single_choice', 'multiple_choice', '选择题', '单选', '多选'], true)) {
- return 'choice';
- }
- if (in_array($type, ['fill', 'fill_in_the_blank', 'blank', '填空题', '填空'], true)) {
- return 'fill';
- }
- if (in_array($type, ['answer', 'calculation', 'word_problem', 'proof', '解答题', '计算题'], true)) {
- return 'answer';
- }
- return null;
- }
- public function normalizeDifficulty(mixed $difficulty): float
- {
- if ($difficulty === null || $difficulty === '') {
- return 0.5;
- }
- $value = (float) $difficulty;
- if ($value > 1) {
- $value = $value / 5;
- }
- return max(0.0, min(1.0, $value));
- }
- private function guessType(array $question): string
- {
- if (! empty($question['options']) && is_array($question['options'])) {
- return 'choice';
- }
- $content = $question['stem'] ?? $question['content'] ?? '';
- if (is_string($content) && (str_contains($content, '____') || str_contains($content, '()'))) {
- return 'fill';
- }
- return 'answer';
- }
- private function defaultScore(string $type): int
- {
- return match ($type) {
- 'choice', 'fill' => 5,
- default => 10,
- };
- }
- }
|