'decimal:4', 'confidence_level' => 'decimal:4', 'mastery_change' => 'decimal:4', 'avg_time_seconds' => 'decimal:2', 'first_attempt_at' => 'datetime', 'last_attempt_at' => 'datetime', 'last_mastery_update' => 'datetime', 'created_at' => 'datetime', 'updated_at' => 'datetime', ]; /** * 关联学生 */ public function student(): BelongsTo { return $this->belongsTo(Student::class, 'student_id', 'student_id'); } /** * 关联知识点 */ public function knowledgePoint(): BelongsTo { return $this->belongsTo(KnowledgePoint::class, 'kp_code', 'kp_code'); } /** * 作用域:按学生筛选 */ public function scopeForStudent($query, string $studentId) { return $query->where('student_id', $studentId); } /** * 作用域:按知识点筛选 */ public function scopeForKnowledgePoint($query, string $kpCode) { return $query->where('kp_code', $kpCode); } /** * 作用域:薄弱点(掌握度低于阈值) */ public function scopeWeaknesses($query, float $threshold = 0.7) { return $query->where('mastery_level', '<', $threshold); } /** * 作用域:按掌握度排序 */ public function scopeOrderByMastery($query, string $direction = 'asc') { return $query->orderBy('mastery_level', $direction); } /** * 获取薄弱点列表 */ public static function getWeaknesses(string $studentId, float $threshold = 0.7, int $limit = 20): array { return self::forStudent($studentId) ->weaknesses($threshold) ->orderByMastery('asc') ->limit($limit) ->get() ->toArray(); } /** * 计算掌握度等级 */ public function getMasteryLevelAttribute($value): string { if ($value >= 0.85) { return '优秀'; } elseif ($value >= 0.70) { return '良好'; } elseif ($value >= 0.50) { return '及格'; } else { return '薄弱'; } } /** * 获取趋势标签 */ public function getTrendLabelAttribute(): string { return match ($this->mastery_trend) { 'improving' => '上升', 'declining' => '下降', 'stable' => '稳定', 'insufficient' => '数据不足', default => '未知', }; } /** * 计算成功率 */ public function getSuccessRateAttribute(): float { if ($this->total_attempts <= 0) { return 0.0; } return round(($this->correct_attempts / $this->total_attempts) * 100, 2); } }