|
|
@@ -4,225 +4,264 @@ namespace App\Services;
|
|
|
|
|
|
use Illuminate\Support\Facades\DB;
|
|
|
use Illuminate\Support\Facades\Log;
|
|
|
-use Illuminate\Support\Collection;
|
|
|
+use Illuminate\Support\Facades\Cache;
|
|
|
|
|
|
class StudentProgressService
|
|
|
{
|
|
|
/**
|
|
|
- * 计算学生学习进度(总体掌握度)
|
|
|
- * 公式:所有子知识点掌握度累加值 / 所有子知识点掌握度的累加值
|
|
|
- *
|
|
|
- * @param string $studentId
|
|
|
- * @return array
|
|
|
+ * 获取单个学生的学习进度
|
|
|
*/
|
|
|
- public function calculateLearningProgress(string $studentId): array
|
|
|
+ public function getProgress(string $studentId): array
|
|
|
{
|
|
|
- try {
|
|
|
- // 1. 获取所有父知识点代码(需要排除的)
|
|
|
- $parentKpCodes = $this->getParentKnowledgePointCodes();
|
|
|
+ Log::info('获取学生学习进度', ['student_id' => $studentId]);
|
|
|
|
|
|
- // 2. 获取学生所有知识点的掌握度数据(合并两个表)
|
|
|
- $allMasteryData = $this->getMergedMasteryData($studentId);
|
|
|
+ // 获取知识图谱结构
|
|
|
+ $graphData = $this->getKnowledgeGraphStructure();
|
|
|
+ $leafKpCodes = $graphData['leafKpCodes'];
|
|
|
+ $leafKpCodesSet = $graphData['leafKpCodesSet'];
|
|
|
+ $kpCodes = $graphData['kpCodes'];
|
|
|
+ $maxChildScore = count($leafKpCodes) * 1.0;
|
|
|
|
|
|
- // 3. 过滤掉父知识点,只保留子知识点
|
|
|
- $childMasteryData = $allMasteryData->filter(function ($item) use ($parentKpCodes) {
|
|
|
- return !in_array($item['kp_code'], $parentKpCodes);
|
|
|
- });
|
|
|
+ // 获取学生掌握度数据
|
|
|
+ $mergedData = $this->getStudentMasteryData($studentId);
|
|
|
|
|
|
- if ($childMasteryData->isEmpty()) {
|
|
|
- return [
|
|
|
- 'success' => false,
|
|
|
- 'error' => '该学生没有子知识点的掌握度数据'
|
|
|
- ];
|
|
|
- }
|
|
|
+ // 如果没有数据,返回空结构(和批量接口行为一致)
|
|
|
+ if (empty($mergedData)) {
|
|
|
+ return [
|
|
|
+ 'success' => true,
|
|
|
+ 'data' => [
|
|
|
+ 'student_id' => $studentId,
|
|
|
+ 'learning_progress' => 0,
|
|
|
+ 'learning_progress_percentage' => 0,
|
|
|
+ 'mastered_child_count' => 0,
|
|
|
+ 'total_child_count' => count($leafKpCodes),
|
|
|
+ 'child_mastery_sum' => 0,
|
|
|
+ 'has_data' => false,
|
|
|
+ 'calculated_at' => now()->toISOString()
|
|
|
+ ],
|
|
|
+ 'message' => '该学生暂无学习数据'
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 筛选叶子节点
|
|
|
+ $childMasteryData = collect($mergedData)->filter(function ($item) use ($leafKpCodesSet) {
|
|
|
+ return isset($leafKpCodesSet[$item['kp_code']]);
|
|
|
+ });
|
|
|
|
|
|
- // 4. 计算总体掌握度
|
|
|
- $totalMasterySum = $childMasteryData->sum('mastery_level');
|
|
|
- $masteryCount = $childMasteryData->count();
|
|
|
- $overallMastery = $masteryCount > 0 ? $totalMasterySum / $masteryCount : 0.0;
|
|
|
-
|
|
|
- // 5. 统计信息
|
|
|
- $statistics = [
|
|
|
- 'total_child_kps' => $masteryCount,
|
|
|
- 'average_mastery' => round($overallMastery, 4),
|
|
|
- 'max_mastery' => round($childMasteryData->max('mastery_level'), 4),
|
|
|
- 'min_mastery' => round($childMasteryData->min('mastery_level'), 4),
|
|
|
- 'data_source' => $this->getDataSourceInfo($allMasteryData),
|
|
|
- 'parent_kp_excluded' => count($parentKpCodes),
|
|
|
- 'mastery_distribution' => $this->getMasteryDistribution($childMasteryData)
|
|
|
+ // 如果没有子知识点数据,也返回空结构
|
|
|
+ if ($childMasteryData->isEmpty()) {
|
|
|
+ return [
|
|
|
+ 'success' => true,
|
|
|
+ 'data' => [
|
|
|
+ 'student_id' => $studentId,
|
|
|
+ 'learning_progress' => 0,
|
|
|
+ 'learning_progress_percentage' => 0,
|
|
|
+ 'mastered_child_count' => 0,
|
|
|
+ 'total_child_count' => count($leafKpCodes),
|
|
|
+ 'child_mastery_sum' => 0,
|
|
|
+ 'has_data' => false,
|
|
|
+ 'calculated_at' => now()->toISOString()
|
|
|
+ ],
|
|
|
+ 'message' => '该学生暂无子知识点学习数据'
|
|
|
];
|
|
|
+ }
|
|
|
|
|
|
- $result = [
|
|
|
+ // 计算学习进度
|
|
|
+ $totalChildMasterySum = $childMasteryData->sum('mastery_level');
|
|
|
+ $learningProgress = $maxChildScore > 0 ? ($totalChildMasterySum / $maxChildScore) : 0.0;
|
|
|
+
|
|
|
+ // 统计信息
|
|
|
+ $statistics = [
|
|
|
+ 'total_knowledge_points' => count($kpCodes),
|
|
|
+ 'child_knowledge_points' => count($leafKpCodes),
|
|
|
+ 'student_mastered_child_count' => $childMasteryData->count(),
|
|
|
+ 'student_mastered_child_percentage' => round(($childMasteryData->count() / count($leafKpCodes)) * 100, 2),
|
|
|
+ 'child_mastery_sum' => round($totalChildMasterySum, 4),
|
|
|
+ 'max_child_score' => round($maxChildScore, 4),
|
|
|
+ 'learning_progress_percentage' => round($learningProgress * 100, 2),
|
|
|
+ 'data_source' => implode(', ', collect($mergedData)->pluck('source_table')->unique()->toArray()),
|
|
|
+ 'child_mastery_max' => round($childMasteryData->max('mastery_level'), 4),
|
|
|
+ 'child_mastery_min' => round($childMasteryData->min('mastery_level'), 4),
|
|
|
+ 'child_mastery_avg' => round($childMasteryData->avg('mastery_level'), 4),
|
|
|
+ ];
|
|
|
+
|
|
|
+ Log::info('学生学习进度计算成功', [
|
|
|
+ 'student_id' => $studentId,
|
|
|
+ 'learning_progress' => $learningProgress,
|
|
|
+ ]);
|
|
|
+
|
|
|
+ return [
|
|
|
+ 'success' => true,
|
|
|
+ 'data' => [
|
|
|
'student_id' => $studentId,
|
|
|
- 'overall_mastery' => round($overallMastery, 4),
|
|
|
+ 'learning_progress' => round($learningProgress, 6),
|
|
|
+ 'learning_progress_percentage' => round($learningProgress * 100, 2),
|
|
|
+ 'mastered_child_count' => $childMasteryData->count(),
|
|
|
+ 'total_child_count' => count($leafKpCodes),
|
|
|
+ 'child_mastery_sum' => round($totalChildMasterySum, 4),
|
|
|
+ 'has_data' => true,
|
|
|
'child_knowledge_points' => $childMasteryData->values()->toArray(),
|
|
|
'statistics' => $statistics,
|
|
|
'calculated_at' => now()->toISOString()
|
|
|
- ];
|
|
|
-
|
|
|
- Log::info('学生学习进度计算成功', [
|
|
|
- 'student_id' => $studentId,
|
|
|
- 'overall_mastery' => $overallMastery,
|
|
|
- 'child_kp_count' => $masteryCount,
|
|
|
- 'parent_kp_excluded' => count($parentKpCodes)
|
|
|
- ]);
|
|
|
+ ],
|
|
|
+ 'message' => '学习进度计算成功'
|
|
|
+ ];
|
|
|
+ }
|
|
|
|
|
|
+ /**
|
|
|
+ * 批量获取学生学习进度
|
|
|
+ */
|
|
|
+ public function getBatchProgress(array $studentIds): array
|
|
|
+ {
|
|
|
+ if (empty($studentIds)) {
|
|
|
return [
|
|
|
- 'success' => true,
|
|
|
- 'data' => $result
|
|
|
+ 'success' => false,
|
|
|
+ 'error' => 'student_ids 不能为空'
|
|
|
];
|
|
|
+ }
|
|
|
|
|
|
- } catch (\Exception $e) {
|
|
|
- Log::error('计算学生学习进度失败', [
|
|
|
- 'student_id' => $studentId,
|
|
|
- 'error' => $e->getMessage()
|
|
|
- ]);
|
|
|
-
|
|
|
+ if (count($studentIds) > 100) {
|
|
|
return [
|
|
|
'success' => false,
|
|
|
- 'error' => '计算学习进度时发生错误: ' . $e->getMessage()
|
|
|
+ 'error' => '单次最多查询 100 个学生'
|
|
|
];
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- /**
|
|
|
- * 获取学生知识点掌握度详情
|
|
|
- *
|
|
|
- * @param string $studentId
|
|
|
- * @return array
|
|
|
- */
|
|
|
- public function getKnowledgePointDetails(string $studentId): array
|
|
|
- {
|
|
|
- try {
|
|
|
- // 获取合并的掌握度数据
|
|
|
- $masteryData = $this->getMergedMasteryData($studentId);
|
|
|
+ Log::info('批量获取学生学习进度', ['count' => count($studentIds)]);
|
|
|
|
|
|
- // 获取父知识点列表
|
|
|
- $parentKpCodes = $this->getParentKnowledgePointCodes();
|
|
|
+ // 获取知识图谱结构(所有学生共用)
|
|
|
+ $graphData = $this->getKnowledgeGraphStructure();
|
|
|
+ $leafKpCodes = $graphData['leafKpCodes'];
|
|
|
+ $leafKpCodesSet = $graphData['leafKpCodesSet'];
|
|
|
+ $maxChildScore = count($leafKpCodes) * 1.0;
|
|
|
|
|
|
- // 分类数据
|
|
|
- $childData = [];
|
|
|
- $parentData = [];
|
|
|
+ // 批量获取掌握度数据
|
|
|
+ $batchData = $this->getBatchStudentMasteryData($studentIds);
|
|
|
+ $detailedData = $batchData['detailed'];
|
|
|
+ $simpleData = $batchData['simple'];
|
|
|
|
|
|
- foreach ($masteryData as $item) {
|
|
|
- if (in_array($item['kp_code'], $parentKpCodes)) {
|
|
|
- $parentData[] = $item;
|
|
|
- } else {
|
|
|
- $childData[] = $item;
|
|
|
+ // 为每个学生计算学习进度
|
|
|
+ $results = [];
|
|
|
+
|
|
|
+ foreach ($studentIds as $studentId) {
|
|
|
+ $studentId = (string) $studentId;
|
|
|
+ $mergedData = [];
|
|
|
+
|
|
|
+ // 从 student_knowledge_mastery 获取
|
|
|
+ if (isset($detailedData[$studentId])) {
|
|
|
+ foreach ($detailedData[$studentId] as $item) {
|
|
|
+ $mergedData[$item->kp_code] = [
|
|
|
+ 'kp_code' => $item->kp_code,
|
|
|
+ 'mastery_level' => (float) $item->mastery_level,
|
|
|
+ ];
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // 获取知识点详细信息
|
|
|
- $knowledgePointDetails = $this->getKnowledgePointDetailsByCodes(
|
|
|
- array_column($masteryData->toArray(), 'kp_code')
|
|
|
- );
|
|
|
-
|
|
|
- // 合并知识点信息
|
|
|
- $enhancedData = [];
|
|
|
- foreach ($masteryData as $item) {
|
|
|
- $kpCode = $item['kp_code'];
|
|
|
- $detail = $knowledgePointDetails[$kpCode] ?? null;
|
|
|
-
|
|
|
- $enhancedData[] = array_merge($item, [
|
|
|
- 'knowledge_point_name' => $detail['name'] ?? '未知知识点',
|
|
|
- 'subject' => $detail['subject'] ?? null,
|
|
|
- 'grade' => $detail['grade'] ?? null,
|
|
|
- 'is_parent' => in_array($kpCode, $parentKpCodes),
|
|
|
- 'parent_kp_code' => $detail['parent_kp_code'] ?? null
|
|
|
- ]);
|
|
|
+ // 从 student_mastery 补充或更新
|
|
|
+ if (isset($simpleData[$studentId])) {
|
|
|
+ foreach ($simpleData[$studentId] as $item) {
|
|
|
+ $kpCode = $item->kp_code;
|
|
|
+ $masteryLevel = (float) $item->mastery;
|
|
|
+
|
|
|
+ if (isset($mergedData[$kpCode])) {
|
|
|
+ if ($masteryLevel > $mergedData[$kpCode]['mastery_level']) {
|
|
|
+ $mergedData[$kpCode]['mastery_level'] = $masteryLevel;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ $mergedData[$kpCode] = [
|
|
|
+ 'kp_code' => $kpCode,
|
|
|
+ 'mastery_level' => $masteryLevel,
|
|
|
+ ];
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- return [
|
|
|
- 'student_id' => $studentId,
|
|
|
- 'mastery_data' => $enhancedData,
|
|
|
- 'summary' => [
|
|
|
- 'total_kps' => count($enhancedData),
|
|
|
- 'child_kps' => count($childData),
|
|
|
- 'parent_kps' => count($parentData),
|
|
|
- 'overall_child_mastery' => count($childData) > 0 ?
|
|
|
- round(array_sum(array_column($childData, 'mastery_level')) / count($childData), 4) : 0.0
|
|
|
- ]
|
|
|
- ];
|
|
|
+ // 计算学习进度
|
|
|
+ if (empty($mergedData)) {
|
|
|
+ $results[$studentId] = [
|
|
|
+ 'student_id' => $studentId,
|
|
|
+ 'learning_progress' => 0,
|
|
|
+ 'learning_progress_percentage' => 0,
|
|
|
+ 'mastered_child_count' => 0,
|
|
|
+ 'total_child_count' => count($leafKpCodes),
|
|
|
+ 'has_data' => false,
|
|
|
+ ];
|
|
|
+ continue;
|
|
|
+ }
|
|
|
|
|
|
- } catch (\Exception $e) {
|
|
|
- Log::error('获取学生知识点掌握度详情失败', [
|
|
|
- 'student_id' => $studentId,
|
|
|
- 'error' => $e->getMessage()
|
|
|
- ]);
|
|
|
+ // 筛选叶子节点并计算
|
|
|
+ $childMasterySum = 0;
|
|
|
+ $masteredChildCount = 0;
|
|
|
|
|
|
- throw $e;
|
|
|
- }
|
|
|
- }
|
|
|
+ foreach ($mergedData as $item) {
|
|
|
+ if (isset($leafKpCodesSet[$item['kp_code']])) {
|
|
|
+ $childMasterySum += $item['mastery_level'];
|
|
|
+ $masteredChildCount++;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- /**
|
|
|
- * 批量计算学生学习进度
|
|
|
- *
|
|
|
- * @param array $studentIds
|
|
|
- * @return array
|
|
|
- */
|
|
|
- public function batchCalculateLearningProgress(array $studentIds): array
|
|
|
- {
|
|
|
- $results = [];
|
|
|
+ $learningProgress = $maxChildScore > 0 ? ($childMasterySum / $maxChildScore) : 0.0;
|
|
|
|
|
|
- foreach ($studentIds as $studentId) {
|
|
|
- $result = $this->calculateLearningProgress($studentId);
|
|
|
- $results[] = [
|
|
|
+ $results[$studentId] = [
|
|
|
'student_id' => $studentId,
|
|
|
- 'success' => $result['success'],
|
|
|
- 'data' => $result['success'] ? $result['data'] : null,
|
|
|
- 'error' => $result['success'] ? null : $result['error']
|
|
|
+ 'learning_progress' => round($learningProgress, 6),
|
|
|
+ 'learning_progress_percentage' => round($learningProgress * 100, 2),
|
|
|
+ 'mastered_child_count' => $masteredChildCount,
|
|
|
+ 'total_child_count' => count($leafKpCodes),
|
|
|
+ 'child_mastery_sum' => round($childMasterySum, 4),
|
|
|
+ 'has_data' => true,
|
|
|
];
|
|
|
}
|
|
|
|
|
|
- return $results;
|
|
|
+ Log::info('批量学习进度计算完成', ['count' => count($results)]);
|
|
|
+
|
|
|
+ return [
|
|
|
+ 'success' => true,
|
|
|
+ 'data' => $results,
|
|
|
+ 'meta' => [
|
|
|
+ 'total_students' => count($studentIds),
|
|
|
+ 'total_child_knowledge_points' => count($leafKpCodes),
|
|
|
+ 'calculated_at' => now()->toISOString(),
|
|
|
+ ]
|
|
|
+ ];
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 获取所有父知识点代码
|
|
|
- *
|
|
|
- * @return array
|
|
|
+ * 获取知识图谱结构(缓存 5 分钟)
|
|
|
*/
|
|
|
- private function getParentKnowledgePointCodes(): array
|
|
|
+ private function getKnowledgeGraphStructure(): array
|
|
|
{
|
|
|
- try {
|
|
|
- $parentCodes = DB::connection('remote_mysql')
|
|
|
+ return Cache::remember('knowledge_graph_structure', 300, function () {
|
|
|
+ $allKps = DB::connection('remote_mysql')
|
|
|
->table('knowledge_points')
|
|
|
- ->whereNotNull('parent_kp_code')
|
|
|
- ->distinct()
|
|
|
- ->pluck('parent_kp_code')
|
|
|
- ->toArray();
|
|
|
+ ->select(['kp_code', 'parent_kp_code'])
|
|
|
+ ->get();
|
|
|
|
|
|
- return array_filter($parentCodes);
|
|
|
- } catch (\Exception $e) {
|
|
|
- Log::error('获取父知识点代码失败', ['error' => $e->getMessage()]);
|
|
|
- return [];
|
|
|
- }
|
|
|
+ $kpCodes = $allKps->pluck('kp_code')->toArray();
|
|
|
+ $parentCodes = $allKps->whereNotNull('parent_kp_code')->pluck('parent_kp_code')->unique()->toArray();
|
|
|
+ $leafKpCodes = array_values(array_diff($kpCodes, $parentCodes));
|
|
|
+
|
|
|
+ return [
|
|
|
+ 'kpCodes' => $kpCodes,
|
|
|
+ 'leafKpCodes' => $leafKpCodes,
|
|
|
+ 'leafKpCodesSet' => array_flip($leafKpCodes),
|
|
|
+ ];
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 获取合并的学生掌握度数据(从两个表)
|
|
|
- *
|
|
|
- * @param string $studentId
|
|
|
- * @return Collection
|
|
|
+ * 获取单个学生的掌握度数据
|
|
|
*/
|
|
|
- private function getMergedMasteryData(string $studentId): Collection
|
|
|
+ private function getStudentMasteryData(string $studentId): array
|
|
|
{
|
|
|
$mergedData = [];
|
|
|
|
|
|
try {
|
|
|
- // 从 student_knowledge_mastery 表获取数据
|
|
|
$detailedData = DB::connection('remote_mysql')
|
|
|
->table('student_knowledge_mastery')
|
|
|
->where('student_id', $studentId)
|
|
|
- ->select([
|
|
|
- 'kp_code',
|
|
|
- 'mastery_level',
|
|
|
- 'total_attempts',
|
|
|
- 'correct_attempts',
|
|
|
- 'updated_at'
|
|
|
- ])
|
|
|
- ->get()
|
|
|
- ->toArray();
|
|
|
+ ->select(['kp_code', 'mastery_level', 'total_attempts', 'correct_attempts', 'updated_at'])
|
|
|
+ ->get();
|
|
|
|
|
|
foreach ($detailedData as $item) {
|
|
|
$mergedData[$item->kp_code] = [
|
|
|
@@ -234,34 +273,21 @@ class StudentProgressService
|
|
|
'updated_at' => $item->updated_at
|
|
|
];
|
|
|
}
|
|
|
-
|
|
|
} catch (\Exception $e) {
|
|
|
- Log::warning('从 student_knowledge_mastery 表获取数据失败', [
|
|
|
- 'student_id' => $studentId,
|
|
|
- 'error' => $e->getMessage()
|
|
|
- ]);
|
|
|
+ Log::warning('从 student_knowledge_mastery 获取数据失败', ['error' => $e->getMessage()]);
|
|
|
}
|
|
|
|
|
|
try {
|
|
|
- // 从 student_mastery 表获取数据(补充或覆盖)
|
|
|
$simpleData = DB::connection('remote_mysql')
|
|
|
->table('student_mastery')
|
|
|
->where('student_id', $studentId)
|
|
|
- ->select([
|
|
|
- 'kp as kp_code',
|
|
|
- 'mastery',
|
|
|
- 'attempts as total_attempts',
|
|
|
- 'correct as correct_attempts',
|
|
|
- 'updated_at'
|
|
|
- ])
|
|
|
- ->get()
|
|
|
- ->toArray();
|
|
|
+ ->select(['kp as kp_code', 'mastery', 'attempts as total_attempts', 'correct as correct_attempts', 'updated_at'])
|
|
|
+ ->get();
|
|
|
|
|
|
foreach ($simpleData as $item) {
|
|
|
$kpCode = $item->kp_code;
|
|
|
$masteryLevel = (float) $item->mastery;
|
|
|
|
|
|
- // 如果已存在,优先使用 mastery_level 更高的数据
|
|
|
if (isset($mergedData[$kpCode])) {
|
|
|
if ($masteryLevel > $mergedData[$kpCode]['mastery_level']) {
|
|
|
$mergedData[$kpCode]['mastery_level'] = $masteryLevel;
|
|
|
@@ -278,97 +304,35 @@ class StudentProgressService
|
|
|
];
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- } catch (\Exception $e) {
|
|
|
- Log::warning('从 student_mastery 表获取数据失败', [
|
|
|
- 'student_id' => $studentId,
|
|
|
- 'error' => $e->getMessage()
|
|
|
- ]);
|
|
|
- }
|
|
|
-
|
|
|
- return collect($mergedData)->values();
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取知识点详细信息
|
|
|
- *
|
|
|
- * @param array $kpCodes
|
|
|
- * @return array
|
|
|
- */
|
|
|
- private function getKnowledgePointDetailsByCodes(array $kpCodes): array
|
|
|
- {
|
|
|
- if (empty($kpCodes)) {
|
|
|
- return [];
|
|
|
- }
|
|
|
-
|
|
|
- try {
|
|
|
- $details = DB::connection('remote_mysql')
|
|
|
- ->table('knowledge_points')
|
|
|
- ->whereIn('kp_code', $kpCodes)
|
|
|
- ->select(['kp_code', 'name', 'subject', 'grade', 'parent_kp_code'])
|
|
|
- ->get()
|
|
|
- ->keyBy('kp_code')
|
|
|
- ->toArray();
|
|
|
-
|
|
|
- return $details;
|
|
|
} catch (\Exception $e) {
|
|
|
- Log::warning('获取知识点详细信息失败', [
|
|
|
- 'kp_codes' => $kpCodes,
|
|
|
- 'error' => $e->getMessage()
|
|
|
- ]);
|
|
|
- return [];
|
|
|
+ Log::warning('从 student_mastery 获取数据失败', ['error' => $e->getMessage()]);
|
|
|
}
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取数据源信息
|
|
|
- *
|
|
|
- * @param Collection $masteryData
|
|
|
- * @return string
|
|
|
- */
|
|
|
- private function getDataSourceInfo(Collection $masteryData): string
|
|
|
- {
|
|
|
- $sourceTables = $masteryData->pluck('source_table')->unique()->toArray();
|
|
|
|
|
|
- if (count($sourceTables) === 1) {
|
|
|
- return $sourceTables[0];
|
|
|
- }
|
|
|
-
|
|
|
- return 'merged (' . implode(', ', $sourceTables) . ')';
|
|
|
+ return $mergedData;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 获取掌握度分布
|
|
|
- *
|
|
|
- * @param Collection $masteryData
|
|
|
- * @return array
|
|
|
+ * 批量获取学生掌握度数据
|
|
|
*/
|
|
|
- private function getMasteryDistribution(Collection $masteryData): array
|
|
|
+ private function getBatchStudentMasteryData(array $studentIds): array
|
|
|
{
|
|
|
- $distribution = [
|
|
|
- 'excellent' => 0, // >= 0.9
|
|
|
- 'good' => 0, // 0.7 - 0.89
|
|
|
- 'fair' => 0, // 0.5 - 0.69
|
|
|
- 'poor' => 0, // < 0.5
|
|
|
- 'unknown' => 0 // 无数据
|
|
|
+ $detailedData = DB::connection('remote_mysql')
|
|
|
+ ->table('student_knowledge_mastery')
|
|
|
+ ->whereIn('student_id', $studentIds)
|
|
|
+ ->select(['student_id', 'kp_code', 'mastery_level'])
|
|
|
+ ->get()
|
|
|
+ ->groupBy('student_id');
|
|
|
+
|
|
|
+ $simpleData = DB::connection('remote_mysql')
|
|
|
+ ->table('student_mastery')
|
|
|
+ ->whereIn('student_id', $studentIds)
|
|
|
+ ->select(['student_id', 'kp as kp_code', 'mastery'])
|
|
|
+ ->get()
|
|
|
+ ->groupBy('student_id');
|
|
|
+
|
|
|
+ return [
|
|
|
+ 'detailed' => $detailedData->toArray(),
|
|
|
+ 'simple' => $simpleData->toArray(),
|
|
|
];
|
|
|
-
|
|
|
- foreach ($masteryData as $item) {
|
|
|
- $mastery = $item['mastery_level'];
|
|
|
-
|
|
|
- if ($mastery >= 0.9) {
|
|
|
- $distribution['excellent']++;
|
|
|
- } elseif ($mastery >= 0.7) {
|
|
|
- $distribution['good']++;
|
|
|
- } elseif ($mastery >= 0.5) {
|
|
|
- $distribution['fair']++;
|
|
|
- } elseif ($mastery > 0) {
|
|
|
- $distribution['poor']++;
|
|
|
- } else {
|
|
|
- $distribution['unknown']++;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return $distribution;
|
|
|
}
|
|
|
-}
|
|
|
+}
|