重构项目结构,移除Assignment相关功能,优化Submission模块
Some checks failed
TechAct / explore-gitea-actions (push) Failing after 12s
Some checks failed
TechAct / explore-gitea-actions (push) Failing after 12s
This commit is contained in:
@@ -43,18 +43,11 @@ namespace Entities.Contracts
|
||||
veryHard
|
||||
}
|
||||
|
||||
public enum QuestionType : byte
|
||||
public enum TypeNameType : byte
|
||||
{
|
||||
Unknown = 0,
|
||||
Spelling, // 拼写
|
||||
Pronunciation, // 给带点字选择正确读音
|
||||
WordFormation, // 组词
|
||||
FillInTheBlanks, // 选词填空 / 补充词语
|
||||
SentenceDictation, // 默写句子
|
||||
SentenceRewriting, // 仿句 / 改写句子
|
||||
ReadingComprehension, // 阅读理解
|
||||
Composition // 作文
|
||||
|
||||
Subject = 0,
|
||||
QuestionType = 1,
|
||||
ExamType = 2,
|
||||
}
|
||||
|
||||
public enum SubjectAreaEnum : byte
|
||||
@@ -90,7 +83,7 @@ namespace Entities.Contracts
|
||||
ComputerScience // 计算机科学
|
||||
}
|
||||
|
||||
public enum AssignmentStructType : byte
|
||||
public enum ExamStructType : byte
|
||||
{
|
||||
[Display(Name = "根节点", Description = "根")]
|
||||
Root,
|
||||
@@ -105,26 +98,12 @@ namespace Entities.Contracts
|
||||
[Display(Name = "选项", Description = "选")]
|
||||
Option
|
||||
}
|
||||
|
||||
public enum ExamType : byte
|
||||
|
||||
public enum UserRoles
|
||||
{
|
||||
[Display(Name = "期中考试", Description = "中")]
|
||||
MidtermExam,
|
||||
|
||||
[Display(Name = "期末考试", Description = "末")]
|
||||
FinalExam,
|
||||
|
||||
[Display(Name = "月考", Description = "月")]
|
||||
MonthlyExam,
|
||||
|
||||
[Display(Name = "周考", Description = "周")]
|
||||
WeeklyExam,
|
||||
|
||||
[Display(Name = "平时测试", Description = "平")]
|
||||
DailyTest,
|
||||
|
||||
[Display(Name = "AI测试", Description = "AI")]
|
||||
AITest,
|
||||
Student,
|
||||
Teacher,
|
||||
Admin
|
||||
}
|
||||
|
||||
public enum SubmissionStatus
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Entities.Contracts
|
||||
{
|
||||
[Table("assignment_class")]
|
||||
public class AssignmentClass
|
||||
{
|
||||
[Key]
|
||||
[Column("assignment_id", Order = 0)]
|
||||
[ForeignKey("Assignment")]
|
||||
public Guid AssignmentId { get; set; }
|
||||
|
||||
[Key]
|
||||
[Column("class_id", Order = 1)]
|
||||
[ForeignKey("Class")]
|
||||
public Guid ClassId { get; set; }
|
||||
|
||||
[Column("assigned_at")]
|
||||
public DateTime AssignedAt { get; set; }
|
||||
|
||||
[Column("deleted")]
|
||||
public bool IsDeleted { get; set; }
|
||||
|
||||
// Navigation Properties
|
||||
public Assignment Assignment { get; set; }
|
||||
public Class Class { get; set; }
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Entities.DTO;
|
||||
|
||||
namespace Entities.Contracts
|
||||
{
|
||||
[Table("assignment_questions")]
|
||||
public class AssignmentQuestion
|
||||
{
|
||||
[Key]
|
||||
[Column("id")]
|
||||
public Guid Id { get; set; }
|
||||
|
||||
[Column("question_id")]
|
||||
public Guid? QuestionId { get; set; }
|
||||
|
||||
[Column("title")]
|
||||
[MaxLength(1024)]
|
||||
public string? Title { get; set; }
|
||||
|
||||
[Column("description")]
|
||||
public Guid? QuestionContextId { get; set; }
|
||||
|
||||
[Required]
|
||||
[Column("question_number")]
|
||||
public byte Index { get; set; }
|
||||
|
||||
[Column("sequence")]
|
||||
public string Sequence { get; set; } = string.Empty;
|
||||
|
||||
[Column("parent_question_group_id")]
|
||||
public Guid? ParentAssignmentQuestionId { get; set; }
|
||||
|
||||
[Column("group_state")]
|
||||
public AssignmentStructType StructType { get; set; } = AssignmentStructType.Question;
|
||||
|
||||
public QuestionType Type { get; set; } = QuestionType.Unknown;
|
||||
|
||||
[Column("created_at")]
|
||||
public DateTime CreatedAt { get; set; }
|
||||
|
||||
[Column("score")]
|
||||
public float? Score { get; set; }
|
||||
|
||||
public bool BCorrect { get; set; }
|
||||
|
||||
[Column("deleted")]
|
||||
public bool IsDeleted { get; set; }
|
||||
|
||||
|
||||
public Question? Question { get; set; }
|
||||
public Assignment? Assignment { get; set; }
|
||||
|
||||
[ForeignKey(nameof(QuestionContextId))]
|
||||
public QuestionContext? QuestionContext { get; set; }
|
||||
|
||||
public ICollection<SubmissionDetail> SubmissionDetails { get; set; }
|
||||
|
||||
[ForeignKey(nameof(ParentAssignmentQuestionId))]
|
||||
public AssignmentQuestion? ParentAssignmentQuestion { get; set; }
|
||||
public ICollection<AssignmentQuestion> ChildrenAssignmentQuestion { get; set; } = new List<AssignmentQuestion>();
|
||||
|
||||
|
||||
public AssignmentQuestion()
|
||||
{
|
||||
Id = Guid.NewGuid();
|
||||
SubmissionDetails = new HashSet<SubmissionDetail>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,19 +10,24 @@ namespace Entities.Contracts
|
||||
{
|
||||
[Key]
|
||||
[Column("class_id")]
|
||||
public int ClassId { get; set; }
|
||||
public Guid Id { get; set; }
|
||||
|
||||
[Column("grade_id")]
|
||||
public int GradeId { get; set; }
|
||||
public Grade Grade { get; set; }
|
||||
public Guid GradeId { get; set; }
|
||||
[ForeignKey(nameof(GradeId))]
|
||||
public virtual Grade Grade { get; set; }
|
||||
|
||||
[Column("index")]
|
||||
public byte Index { get; set; }
|
||||
|
||||
[Column("class_name")]
|
||||
[MaxLength(30)]
|
||||
public string ClassName { get; set; }
|
||||
|
||||
[Column("head_teacher_id")]
|
||||
public int? HeadTeacherId { get; set; }
|
||||
public User HeadTeacher { get; set; }
|
||||
public Guid? HeadTeacherId { get; set; }
|
||||
[ForeignKey(nameof(HeadTeacherId))]
|
||||
public virtual User HeadTeacher { get; set; }
|
||||
|
||||
[Column("created_at")]
|
||||
public DateTime CreatedAt { get; set; }
|
||||
@@ -34,15 +39,20 @@ namespace Entities.Contracts
|
||||
public bool IsDeleted { get; set; }
|
||||
|
||||
// Navigation Properties
|
||||
public ICollection<ClassTeacher> ClassTeachers { get; set; }
|
||||
public ICollection<ClassStudent> ClassStudents { get; set; }
|
||||
public ICollection<AssignmentClass> AssignmentClasses { get; set; }
|
||||
|
||||
[NotMapped]
|
||||
public ICollection<ClassUser> Techers => ClassUsers.Where(cu => cu.User.Role == UserRoles.Teacher).ToList();
|
||||
|
||||
[NotMapped]
|
||||
public ICollection<ClassUser> Students => ClassUsers.Where(cu => cu.User.Role == UserRoles.Student).ToList();
|
||||
|
||||
[InverseProperty(nameof(ClassUser.Class))]
|
||||
public virtual ICollection<ClassUser> ClassUsers { get; set; }
|
||||
|
||||
public Class()
|
||||
{
|
||||
ClassStudents = new HashSet<ClassStudent>();
|
||||
ClassTeachers = new HashSet<ClassTeacher>();
|
||||
AssignmentClasses = new HashSet<AssignmentClass>();
|
||||
Id = Guid.NewGuid();
|
||||
ClassUsers = new HashSet<ClassUser>();
|
||||
CreatedAt = DateTime.Now;
|
||||
UpdatedAt = DateTime.Now;
|
||||
}
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Entities.Contracts
|
||||
{
|
||||
[Table("class_student")]
|
||||
public class ClassStudent
|
||||
{
|
||||
[Key]
|
||||
[Column("class_id", Order = 0)]
|
||||
[ForeignKey("Class")]
|
||||
public Guid ClassId { get; set; }
|
||||
|
||||
[Key]
|
||||
[Column("student_id", Order = 1)]
|
||||
[ForeignKey("Student")]
|
||||
public Guid StudentId { get; set; }
|
||||
|
||||
[Column("enrollment_date")]
|
||||
public DateTime EnrollmentDate { get; set; }
|
||||
|
||||
[Column("deleted")]
|
||||
public bool IsDeleted { get; set; }
|
||||
|
||||
// Navigation Properties
|
||||
public Class Class { get; set; }
|
||||
public User Student { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Entities.Contracts
|
||||
{
|
||||
[Table("class_teachers")]
|
||||
public class ClassTeacher
|
||||
{
|
||||
[Key]
|
||||
[Column("class_id")]
|
||||
public Guid ClassId { get; set; }
|
||||
[ForeignKey(nameof(ClassId))]
|
||||
public Class Class { get; set; }
|
||||
|
||||
[Key]
|
||||
[Column("teacher_id")]
|
||||
public Guid TeacherId { get; set; }
|
||||
[ForeignKey(nameof(TeacherId))]
|
||||
public User Teacher { get; set; }
|
||||
|
||||
[Column("subject_taught")]
|
||||
public SubjectAreaEnum SubjectTaught { get; set; }
|
||||
}
|
||||
}
|
||||
56
Entities/Contracts/ClassUser.cs
Normal file
56
Entities/Contracts/ClassUser.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Entities.Contracts
|
||||
{
|
||||
/// <summary>
|
||||
/// 班级用户关联实体类
|
||||
/// 表示用户与班级之间的多对多关系
|
||||
/// </summary>
|
||||
[Table("class_user")]
|
||||
[PrimaryKey(nameof(ClassId), nameof(UserId))]
|
||||
public class ClassUser
|
||||
{
|
||||
/// <summary>
|
||||
/// 班级ID,复合主键的一部分,外键
|
||||
/// 关联到Class表中的班级
|
||||
/// </summary>
|
||||
[Key]
|
||||
[Column("class_id", Order = 0)]
|
||||
public Guid ClassId { get; set; }
|
||||
[ForeignKey(nameof(ClassId))]
|
||||
public virtual Class Class { get; set; }
|
||||
/// <summary>
|
||||
/// 用户ID,复合主键的一部分,外键
|
||||
/// 关联到User表中的用户用户
|
||||
/// </summary>
|
||||
[Key]
|
||||
[Column("student_id", Order = 1)]
|
||||
public Guid UserId { get; set; }
|
||||
[ForeignKey(nameof(UserId))]
|
||||
public virtual User User { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 入学日期
|
||||
/// 记录用户加入该班级的日期
|
||||
/// </summary>
|
||||
[Column("enrollment_date")]
|
||||
public DateTime EnrollmentDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否已删除
|
||||
/// 软删除标记,true表示已删除
|
||||
/// </summary>
|
||||
[Column("deleted")]
|
||||
public bool IsDeleted { get; set; }
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -9,8 +9,8 @@ using Entities.DTO;
|
||||
|
||||
namespace Entities.Contracts
|
||||
{
|
||||
[Table("assignments")]
|
||||
public class Assignment
|
||||
[Table("exams")]
|
||||
public class Exam
|
||||
{
|
||||
[Key]
|
||||
[Column("id")]
|
||||
@@ -24,12 +24,26 @@ namespace Entities.Contracts
|
||||
[Column("description")]
|
||||
public string Description { get; set; }
|
||||
|
||||
[Column("subject_area")]
|
||||
public SubjectAreaEnum SubjectArea { get; set; }
|
||||
[Column("subject_id")]
|
||||
public Guid SubjectId { get; set; }
|
||||
[ForeignKey(nameof(SubjectId))]
|
||||
public virtual Subject Subject { get; set; }
|
||||
|
||||
[Required]
|
||||
[Column("exam_struct_id")]
|
||||
[ForeignKey(nameof(ExamStruct))]
|
||||
public Guid ExamStructId { get; set; }
|
||||
public virtual ExamQuestion ExamStruct { get; set; }
|
||||
|
||||
[Column("exam_type_id")]
|
||||
public Guid ExamTypeId { get; set; }
|
||||
[ForeignKey(nameof(ExamTypeId))]
|
||||
public virtual ExamType ExamType { get; set; }
|
||||
|
||||
[Column("created_by")]
|
||||
public Guid CreatorId { get; set; }
|
||||
[ForeignKey(nameof(CreatorId))]
|
||||
public virtual User Creator { get; set; }
|
||||
|
||||
[Required]
|
||||
[Column("due_date")]
|
||||
@@ -41,13 +55,9 @@ namespace Entities.Contracts
|
||||
[Column("score")]
|
||||
public float Score { get; set; }
|
||||
|
||||
[Column("name")]
|
||||
public string Name { get; set; } = string.Empty;
|
||||
|
||||
public ExamType ExamType { get; set; } = ExamType.DailyTest;
|
||||
|
||||
[Column("created_by")]
|
||||
public Guid CreatorId { get; set; }
|
||||
|
||||
[Column("created_at")]
|
||||
public DateTime CreatedAt { get; set; }
|
||||
|
||||
@@ -57,61 +67,53 @@ namespace Entities.Contracts
|
||||
[Column("deleted")]
|
||||
public bool IsDeleted { get; set; } = false;
|
||||
|
||||
// Navigation Properties
|
||||
|
||||
[ForeignKey(nameof(CreatorId))]
|
||||
public User Creator { get; set; }
|
||||
public ICollection<AssignmentClass> AssignmentClasses { get; set; }
|
||||
[InverseProperty(nameof(ExamAttachment.Exam))]
|
||||
public virtual ICollection<ExamAttachment> ExamAttachments { get; set; }
|
||||
[InverseProperty(nameof(Submission.Exam))]
|
||||
public virtual ICollection<Submission> Submissions { get; set; }
|
||||
|
||||
[ForeignKey(nameof(ExamStructId))]
|
||||
public AssignmentQuestion ExamStruct { get; set; }
|
||||
public ICollection<AssignmentAttachment> AssignmentAttachments { get; set; }
|
||||
public ICollection<Submission> Submissions { get; set; }
|
||||
|
||||
public Assignment()
|
||||
public Exam()
|
||||
{
|
||||
Id = Guid.NewGuid();
|
||||
|
||||
ExamAttachments = new HashSet<ExamAttachment>();
|
||||
Submissions = new HashSet<Submission>();
|
||||
AssignmentClasses = new HashSet<AssignmentClass>();
|
||||
AssignmentAttachments = new HashSet<AssignmentAttachment>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class AssignmentExt
|
||||
public static class examExt
|
||||
{
|
||||
public static Submission ConvertToSubmission(this Assignment assignment, Guid studentId, Guid GraderId)
|
||||
public static Submission ConvertToSubmission(this Exam exam, Guid studentId, Guid GraderId, Guid classId)
|
||||
{
|
||||
if (assignment == null) return new Submission();
|
||||
if (exam == null) return new Submission();
|
||||
var submission = new Submission();
|
||||
|
||||
submission.StudentId = studentId;
|
||||
submission.SubmissionTime = DateTime.Now;
|
||||
submission.Status = SubmissionStatus.Pending;
|
||||
submission.GraderId = GraderId;
|
||||
submission.AssignmentId = assignment.Id;
|
||||
|
||||
ConvertExamSturctToSubmissionDetails(assignment.ExamStruct, studentId, submission.SubmissionDetails);
|
||||
submission.ExamId = exam.Id;
|
||||
submission.ClassId = classId;
|
||||
ConvertExamSturctToSubmissionDetails(exam.ExamStruct, studentId, submission.SubmissionDetails);
|
||||
|
||||
return submission;
|
||||
}
|
||||
|
||||
|
||||
public static void ConvertExamSturctToSubmissionDetails(AssignmentQuestion examStruct, Guid studentId, ICollection<SubmissionDetail> submissions)
|
||||
public static void ConvertExamSturctToSubmissionDetails(ExamQuestion examStruct, Guid studentId, ICollection<SubmissionDetail> submissions)
|
||||
{
|
||||
if (examStruct == null) return;
|
||||
submissions.Add(new SubmissionDetail
|
||||
{
|
||||
StudentId = studentId,
|
||||
AssignmentQuestionId = examStruct.Id,
|
||||
IsCorrect = true,
|
||||
ExamQuestionId = examStruct.Id,
|
||||
CreatedAt = DateTime.Now,
|
||||
UpdatedAt = DateTime.Now,
|
||||
Status = SubmissionStatus.Pending,
|
||||
});
|
||||
|
||||
examStruct.ChildrenAssignmentQuestion?.ToList().ForEach(s =>
|
||||
examStruct.ChildExamQuestions?.ToList().ForEach(s =>
|
||||
{
|
||||
ConvertExamSturctToSubmissionDetails(s, studentId, submissions);
|
||||
});
|
||||
@@ -9,17 +9,18 @@ using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Entities.Contracts
|
||||
{
|
||||
[Table("assignment_attachments")]
|
||||
public class AssignmentAttachment
|
||||
[Table("exam_attachments")]
|
||||
public class ExamAttachment
|
||||
{
|
||||
[Key]
|
||||
[Column("id")]
|
||||
public Guid Id { get; set; }
|
||||
|
||||
[Required]
|
||||
[Column("assignment_id")]
|
||||
[ForeignKey("Assignment")]
|
||||
public Guid AssignmentId { get; set; }
|
||||
[Column("exam_id")]
|
||||
public Guid ExamId { get; set; }
|
||||
[ForeignKey(nameof(ExamId))]
|
||||
public virtual Exam Exam { get; set; }
|
||||
|
||||
[Required]
|
||||
[Column("file_path")]
|
||||
@@ -37,10 +38,7 @@ namespace Entities.Contracts
|
||||
[Column("deleted")]
|
||||
public bool IsDeleted { get; set; }
|
||||
|
||||
// Navigation Properties
|
||||
public Assignment Assignment { get; set; }
|
||||
|
||||
public AssignmentAttachment()
|
||||
public ExamAttachment()
|
||||
{
|
||||
Id = Guid.NewGuid();
|
||||
}
|
||||
71
Entities/Contracts/ExamQuestion.cs
Normal file
71
Entities/Contracts/ExamQuestion.cs
Normal file
@@ -0,0 +1,71 @@
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Entities.DTO;
|
||||
|
||||
namespace Entities.Contracts
|
||||
{
|
||||
[Table("exam_questions")]
|
||||
public class ExamQuestion
|
||||
{
|
||||
[Key]
|
||||
[Column("id")]
|
||||
public Guid Id { get; set; }
|
||||
|
||||
[Column("title")]
|
||||
[MaxLength(1024)]
|
||||
public string? Title { get; set; }
|
||||
|
||||
[Column("question_id")]
|
||||
public Guid? QuestionId { get; set; }
|
||||
[ForeignKey(nameof(QuestionId))]
|
||||
public virtual Question? Question { get; set; }
|
||||
|
||||
[Column("description")]
|
||||
public Guid? QuestionContextId { get; set; }
|
||||
[ForeignKey(nameof(QuestionContextId))]
|
||||
public virtual QuestionContext? QuestionContext { get; set; }
|
||||
|
||||
[Required]
|
||||
[Column("question_number")]
|
||||
public byte Index { get; set; }
|
||||
|
||||
[Column("sequence")]
|
||||
public string Sequence { get; set; } = string.Empty;
|
||||
|
||||
[Column("parent_question_group_id")]
|
||||
public Guid? ParentExamQuestionId { get; set; }
|
||||
[ForeignKey(nameof(ParentExamQuestionId))]
|
||||
public virtual ExamQuestion? ParentExamQuestion { get; set; }
|
||||
|
||||
public Guid QuestionTypeId { get;set; }
|
||||
[ForeignKey(nameof(QuestionTypeId))]
|
||||
public virtual QuestionType Type { get; set; }
|
||||
|
||||
[Column("created_at")]
|
||||
public DateTime CreatedAt { get; set; }
|
||||
|
||||
[Column("exam_struct_type")]
|
||||
public ExamStructType ExamStructType { get; set; }
|
||||
|
||||
[Column("score")]
|
||||
public float? Score { get; set; }
|
||||
|
||||
[Column("deleted")]
|
||||
public bool IsDeleted { get; set; }
|
||||
|
||||
|
||||
public virtual Exam? Exam { get; set; }
|
||||
|
||||
|
||||
[InverseProperty(nameof(SubmissionDetail.ExamQuestion))]
|
||||
public virtual ICollection<SubmissionDetail> SubmissionDetails { get; set; }
|
||||
[InverseProperty(nameof(ParentExamQuestion))]
|
||||
public virtual ICollection<ExamQuestion> ChildExamQuestions { get; set; } = new List<ExamQuestion>();
|
||||
|
||||
public ExamQuestion()
|
||||
{
|
||||
Id = Guid.NewGuid();
|
||||
SubmissionDetails = new HashSet<SubmissionDetail>();
|
||||
}
|
||||
}
|
||||
}
|
||||
30
Entities/Contracts/ExamType.cs
Normal file
30
Entities/Contracts/ExamType.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace Entities.Contracts
|
||||
{
|
||||
[Table("exam_type")]
|
||||
public class ExamType
|
||||
{
|
||||
[Key]
|
||||
[Column("id")]
|
||||
public Guid Id { get; set; }
|
||||
|
||||
[Column("name")]
|
||||
[MaxLength(20)]
|
||||
public string Name { get; set; }
|
||||
|
||||
[Column("description")]
|
||||
public string Description { get; set; }
|
||||
|
||||
[InverseProperty(nameof(Exam.ExamType))]
|
||||
public virtual ICollection<Exam> Exams { get; set; }
|
||||
|
||||
public ExamType()
|
||||
{
|
||||
Id = Guid.NewGuid();
|
||||
Exams = new HashSet<Exam>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Entities.Contracts
|
||||
{
|
||||
[Table("global")]
|
||||
public class Global
|
||||
{
|
||||
[Key]
|
||||
[Column("id")]
|
||||
public Guid Id { get; set; } = Guid.NewGuid();
|
||||
|
||||
public SubjectAreaEnum Area { get; set; }
|
||||
|
||||
public string Info { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -10,24 +10,25 @@ namespace Entities.Contracts
|
||||
{
|
||||
[Key]
|
||||
[Column("grade_id")]
|
||||
public int GradeId { get; set; }
|
||||
public Guid Id { get; set; }
|
||||
|
||||
[Column("school_id")]
|
||||
public int SchoolId { get; set; }
|
||||
public School School { get; set; }
|
||||
public Guid SchoolId { get; set; }
|
||||
public virtual School School { get; set; }
|
||||
|
||||
[Column("grade_name")]
|
||||
[MaxLength(20)]
|
||||
public string GradeName { get; set; }
|
||||
|
||||
[Column("grade_level")]
|
||||
public int GradeLevel { get; set; }
|
||||
public byte GradeLevel { get; set; }
|
||||
|
||||
// Navigation Properties
|
||||
public ICollection<Class> Classes { get; set; }
|
||||
[InverseProperty(nameof(Class.Grade))]
|
||||
public virtual ICollection<Class> Classes { get; set; }
|
||||
|
||||
public Grade()
|
||||
{
|
||||
Id = Guid.NewGuid();
|
||||
Classes = new HashSet<Class>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,35 +24,38 @@ namespace Entities.Contracts
|
||||
[MaxLength(65535)]
|
||||
public string? Answer { get; set; }
|
||||
|
||||
|
||||
|
||||
[Required]
|
||||
[Column("type")]
|
||||
[MaxLength(20)]
|
||||
public QuestionType Type { get; set; } = QuestionType.Unknown;
|
||||
|
||||
[Column("difficulty_level")]
|
||||
[MaxLength(10)]
|
||||
public DifficultyLevel DifficultyLevel { get; set; } = DifficultyLevel.easy;
|
||||
public Guid QuestioTypeId { get; set; }
|
||||
[ForeignKey(nameof(QuestioTypeId))]
|
||||
public virtual QuestionType QuestionType { get; set; }
|
||||
|
||||
[Column("subject_area")]
|
||||
public SubjectAreaEnum SubjectArea { get; set; } = SubjectAreaEnum.Unknown;
|
||||
|
||||
public string QType { get; set; } = string.Empty;
|
||||
|
||||
[Column("options")]
|
||||
public string? Options { get; set; }
|
||||
public Guid SubjectId { get; set; }
|
||||
[ForeignKey(nameof(SubjectId))]
|
||||
public virtual Subject Subject { get; set; }
|
||||
|
||||
[Column("key_point")]
|
||||
public Guid? KeyPointId { get; set; }
|
||||
[ForeignKey(nameof(KeyPointId))]
|
||||
public virtual KeyPoint? KeyPoint { get; set; }
|
||||
|
||||
[Column("lesson")]
|
||||
public Guid? LessonId { get; set; }
|
||||
[ForeignKey(nameof(LessonId))]
|
||||
public virtual Lesson? Lesson { get; set; }
|
||||
|
||||
|
||||
[Required]
|
||||
[Column("created_by")]
|
||||
public Guid CreatorId { get; set; }
|
||||
//[Required]
|
||||
//[Column("created_by")]
|
||||
//public Guid CreatorId { get; set; }
|
||||
//[ForeignKey(nameof(CreatorId))]
|
||||
//public virtual User Creator { get; set; }
|
||||
|
||||
//[Column("difficulty_level")]
|
||||
//public DifficultyLevel DifficultyLevel { get; set; } = DifficultyLevel.easy;
|
||||
|
||||
[Column("options")]
|
||||
public string? Options { get; set; }
|
||||
|
||||
[Column("created_at")]
|
||||
public DateTime CreatedAt { get; set; }
|
||||
@@ -63,22 +66,13 @@ namespace Entities.Contracts
|
||||
[Column("deleted")]
|
||||
public bool IsDeleted { get; set; }
|
||||
|
||||
|
||||
// Navigation Properties
|
||||
[ForeignKey(nameof(CreatorId))]
|
||||
public User Creator { get; set; }
|
||||
|
||||
[ForeignKey(nameof(KeyPointId))]
|
||||
public KeyPoint? KeyPoint { get; set; }
|
||||
[ForeignKey(nameof(LessonId))]
|
||||
public Lesson? Lesson { get; set; }
|
||||
|
||||
public ICollection<AssignmentQuestion>? AssignmentQuestions { get; set; }
|
||||
[InverseProperty(nameof(ExamQuestion.Question))]
|
||||
public virtual ICollection<ExamQuestion>? ExamQuestions { get; set; }
|
||||
|
||||
public Question()
|
||||
{
|
||||
Id = Guid.NewGuid();
|
||||
AssignmentQuestions = new HashSet<AssignmentQuestion>();
|
||||
ExamQuestions = new HashSet<ExamQuestion>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,13 +13,13 @@ namespace Entities.Contracts
|
||||
|
||||
public string Description { get; set; } = string.Empty;
|
||||
|
||||
[InverseProperty(nameof(AssignmentQuestion.QuestionContext))]
|
||||
public ICollection<AssignmentQuestion>? Questions { get; set; } = new List<AssignmentQuestion>();
|
||||
[InverseProperty(nameof(ExamQuestion.QuestionContext))]
|
||||
public virtual ICollection<ExamQuestion>? Questions { get; set; } = new List<ExamQuestion>();
|
||||
|
||||
|
||||
public QuestionContext()
|
||||
{
|
||||
Questions = new HashSet<AssignmentQuestion>();
|
||||
Questions = new HashSet<ExamQuestion>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
40
Entities/Contracts/QuestionType.cs
Normal file
40
Entities/Contracts/QuestionType.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace Entities.Contracts
|
||||
{
|
||||
[Table("question_types")]
|
||||
public class QuestionType
|
||||
{
|
||||
[Key]
|
||||
[Column("id")]
|
||||
public Guid Id { get; set; }
|
||||
|
||||
[Column("name")]
|
||||
[MaxLength(20)]
|
||||
public string Name { get; set; }
|
||||
|
||||
[Column("subject_id")]
|
||||
public Guid SubjectId { get; set; }
|
||||
[ForeignKey(nameof(SubjectId))]
|
||||
public virtual Subject Subject { get; set; }
|
||||
|
||||
[Column("description")]
|
||||
public string Description { get; set; }
|
||||
|
||||
[Column("score_rule")]
|
||||
[MaxLength(20)]
|
||||
public string ScoreRule { get; set; }
|
||||
|
||||
[InverseProperty(nameof(Question.QuestionType))]
|
||||
public virtual IEnumerable<Question> Questions { get; set; }
|
||||
|
||||
public QuestionType()
|
||||
{
|
||||
Id = Guid.NewGuid();
|
||||
|
||||
Questions = new HashSet<Question>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,8 +9,8 @@ namespace Entities.Contracts
|
||||
public class School
|
||||
{
|
||||
[Key]
|
||||
[Column("school_id")]
|
||||
public int SchoolId { get; set; }
|
||||
[Column("id")]
|
||||
public Guid Id { get; set; }
|
||||
|
||||
[Column("school_name")]
|
||||
[MaxLength(50)]
|
||||
@@ -23,11 +23,12 @@ namespace Entities.Contracts
|
||||
[Column("create_time")]
|
||||
public DateTime CreateTime { get; set; }
|
||||
|
||||
// Navigation Properties
|
||||
public ICollection<Grade> Grades { get; set; }
|
||||
[InverseProperty(nameof(Grade.School))]
|
||||
public virtual ICollection<Grade> Grades { get; set; }
|
||||
|
||||
public School()
|
||||
{
|
||||
Id = Guid.NewGuid();
|
||||
Grades = new HashSet<Grade>();
|
||||
CreateTime = DateTime.Now;
|
||||
}
|
||||
|
||||
36
Entities/Contracts/Subject.cs
Normal file
36
Entities/Contracts/Subject.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace Entities.Contracts
|
||||
{
|
||||
[Table("subjects")]
|
||||
public class Subject
|
||||
{
|
||||
[Key]
|
||||
[Column("id")]
|
||||
public Guid Id { get; set; }
|
||||
|
||||
[Column("name")]
|
||||
[MaxLength(20)]
|
||||
public string Name { get; set; }
|
||||
|
||||
[Column("description")]
|
||||
public string Description { get; set; }
|
||||
|
||||
[InverseProperty(nameof(QuestionType.Subject))]
|
||||
public virtual IEnumerable<QuestionType> QuestionTypes { get; set; }
|
||||
|
||||
[InverseProperty(nameof(Question.Subject))]
|
||||
public virtual IEnumerable<Question> Questions { get; set; }
|
||||
|
||||
[InverseProperty(nameof(User.TeachSubject))]
|
||||
public virtual IEnumerable<User> SubjectTeachers { get; set; }
|
||||
public Subject()
|
||||
{
|
||||
Id = Guid.NewGuid();
|
||||
QuestionTypes = new HashSet<QuestionType>();
|
||||
Questions = new HashSet<Question>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,18 +17,30 @@ namespace Entities.Contracts
|
||||
public Guid Id { get; set; }
|
||||
|
||||
[Required]
|
||||
[Column("assignment_id")]
|
||||
[ForeignKey("Assignment")]
|
||||
public Guid AssignmentId { get; set; }
|
||||
[Column("exam_id")]
|
||||
public Guid ExamId { get; set; }
|
||||
[ForeignKey(nameof(ExamId))]
|
||||
public virtual Exam Exam { get; set; }
|
||||
|
||||
[Required]
|
||||
[Column("student_id")]
|
||||
[ForeignKey("Student")]
|
||||
public Guid StudentId { get; set; }
|
||||
[ForeignKey(nameof(StudentId))]
|
||||
public virtual User Student { get; set; }
|
||||
|
||||
[Column("graded_by")]
|
||||
public Guid? GraderId { get; set; }
|
||||
[ForeignKey(nameof(GraderId))]
|
||||
public virtual User Grader { get; set; }
|
||||
|
||||
[Column("class_id")]
|
||||
public Guid ClassId { get; set; }
|
||||
[ForeignKey(nameof(ClassId))]
|
||||
public virtual Class Class { get; set; }
|
||||
|
||||
[Required]
|
||||
[Column("attempt_number")]
|
||||
public byte AttemptNumber { get; set; }
|
||||
public byte AttemptNumber { get; set; } // 第几次提交
|
||||
|
||||
[Column("submission_time")]
|
||||
public DateTime SubmissionTime { get; set; }
|
||||
@@ -39,31 +51,36 @@ namespace Entities.Contracts
|
||||
[Column("overall_feedback")]
|
||||
public string? OverallFeedback { get; set; }
|
||||
|
||||
[Column("graded_by")]
|
||||
[ForeignKey("Grader")]
|
||||
public Guid? GraderId { get; set; }
|
||||
|
||||
[Column("graded_at")]
|
||||
public DateTime? GradedAt { get; set; }
|
||||
|
||||
[Column("deleted")]
|
||||
public bool IsDeleted { get; set; }
|
||||
|
||||
public byte TotalQuesNum { get; set; }
|
||||
|
||||
public byte ErrorQuesNum { get; set; }
|
||||
|
||||
public byte TotalScore { get; set; }
|
||||
|
||||
[Required]
|
||||
[Column("status")]
|
||||
public SubmissionStatus Status { get; set; }
|
||||
|
||||
[Column("deleted")]
|
||||
public bool IsDeleted { get; set; }
|
||||
// Navigation Properties
|
||||
public Assignment Assignment { get; set; }
|
||||
public User Student { get; set; }
|
||||
public User Grader { get; set; }
|
||||
public ICollection<SubmissionDetail> SubmissionDetails { get; set; }
|
||||
|
||||
[NotMapped]
|
||||
public int ErrorCount => SubmissionDetails.Where(sd => sd?.IsCorrect == false && sd.IsCorrect != null).Count();
|
||||
|
||||
[NotMapped]
|
||||
public Dictionary<string, int> ErrorQuestionTypeDistribution => SubmissionDetails
|
||||
.Where(sd => sd?.IsCorrect == false)
|
||||
.GroupBy(sd => sd.ExamQuestion.Type.Name)
|
||||
.ToDictionary(g => g.Key, g => g.Count());
|
||||
|
||||
[NotMapped]
|
||||
public Dictionary<string, int> ErrorQuestionLessonDistribution => SubmissionDetails
|
||||
.Where(sd => sd?.IsCorrect == false && sd.ExamQuestion.Question?.Lesson != null)
|
||||
.GroupBy(sd => sd.ExamQuestion.Question.Lesson.Title)
|
||||
.ToDictionary(g => g.Key, g => g.Count());
|
||||
|
||||
|
||||
|
||||
[InverseProperty(nameof(SubmissionDetail.Submission))]
|
||||
public virtual ICollection<SubmissionDetail> SubmissionDetails { get; set; }
|
||||
|
||||
public Submission()
|
||||
{
|
||||
|
||||
@@ -20,15 +20,20 @@ namespace Entities.Contracts
|
||||
[Column("submission_id")]
|
||||
[ForeignKey("Submission")]
|
||||
public Guid SubmissionId { get; set; }
|
||||
[ForeignKey(nameof(SubmissionId))]
|
||||
public virtual Submission Submission { get; set; }
|
||||
|
||||
[Required]
|
||||
[Column("student_id")]
|
||||
public Guid StudentId { get; set; }
|
||||
[ForeignKey(nameof(StudentId))]
|
||||
public virtual User Student { get; set; }
|
||||
|
||||
[Required]
|
||||
[Column("assignment_question_id")]
|
||||
[ForeignKey("AssignmentQuestion")]
|
||||
public Guid AssignmentQuestionId { get; set; }
|
||||
[Column("exam_question_id")]
|
||||
public Guid ExamQuestionId { get; set; }
|
||||
[ForeignKey(nameof(ExamQuestionId))]
|
||||
public virtual ExamQuestion ExamQuestion { get; set; }
|
||||
|
||||
[Column("student_answer")]
|
||||
public string? StudentAnswer { get; set; }
|
||||
@@ -37,7 +42,7 @@ namespace Entities.Contracts
|
||||
public bool? IsCorrect { get; set; }
|
||||
|
||||
[Column("points_awarded")]
|
||||
public float? PointsAwarded { get; set; } // score
|
||||
public float? PointsAwarded { get; set; } // 得分
|
||||
|
||||
[Column("teacher_feedback")]
|
||||
public string? TeacherFeedback { get; set; }
|
||||
@@ -51,20 +56,6 @@ namespace Entities.Contracts
|
||||
[Column("deleted")]
|
||||
public bool IsDeleted { get; set; }
|
||||
|
||||
[Required]
|
||||
[Column("status")]
|
||||
public SubmissionStatus Status { get; set; }
|
||||
|
||||
|
||||
|
||||
[ForeignKey(nameof(StudentId))]
|
||||
public User Student { get; set; }
|
||||
|
||||
[ForeignKey(nameof(SubmissionId))]
|
||||
public Submission Submission { get; set; }
|
||||
|
||||
[ForeignKey(nameof(AssignmentQuestionId))]
|
||||
public AssignmentQuestion AssignmentQuestion { get; set; }
|
||||
|
||||
public SubmissionDetail()
|
||||
{
|
||||
|
||||
@@ -18,14 +18,14 @@ namespace Entities.Contracts
|
||||
public string Key { get; set; } = string.Empty;
|
||||
|
||||
|
||||
|
||||
[Required]
|
||||
public Guid LessonID { get; set; }
|
||||
|
||||
[ForeignKey(nameof(LessonID))]
|
||||
public Lesson Lesson { get; set; }
|
||||
public virtual Lesson Lesson { get; set; }
|
||||
|
||||
|
||||
public ICollection<Question> Questions { get; set; }
|
||||
public virtual ICollection<Question> Questions { get; set; }
|
||||
|
||||
public KeyPoint()
|
||||
{
|
||||
|
||||
@@ -21,19 +21,19 @@ namespace Entities.Contracts
|
||||
|
||||
[Required]
|
||||
public Guid TextbookID { get; set; }
|
||||
|
||||
|
||||
[ForeignKey(nameof(TextbookID))]
|
||||
public Textbook Textbook { get; set; }
|
||||
public virtual Textbook Textbook { get; set; }
|
||||
|
||||
|
||||
|
||||
[InverseProperty(nameof(KeyPoint.Lesson))]
|
||||
public ICollection<KeyPoint>? KeyPoints { get; set; }
|
||||
public virtual ICollection<KeyPoint>? KeyPoints { get; set; }
|
||||
|
||||
[InverseProperty(nameof(Question.Lesson))]
|
||||
public ICollection<Question>? Questions { get; set; }
|
||||
public virtual ICollection<Question>? Questions { get; set; }
|
||||
|
||||
[InverseProperty(nameof(LessonQuestion.Lesson))]
|
||||
public ICollection<LessonQuestion>? LessonQuestions { get; set; }
|
||||
public virtual ICollection<LessonQuestion>? LessonQuestions { get; set; }
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -19,9 +19,9 @@ namespace Entities.Contracts
|
||||
|
||||
[Required]
|
||||
public Guid LessonID { get; set; }
|
||||
|
||||
[ForeignKey(nameof(LessonID))]
|
||||
public Lesson Lesson { get; set; }
|
||||
public virtual Lesson Lesson { get; set; }
|
||||
|
||||
|
||||
public LessonQuestion()
|
||||
{
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace Entities.Contracts
|
||||
public SubjectAreaEnum SubjectArea { get; set; } = SubjectAreaEnum.Unknown;
|
||||
|
||||
[InverseProperty(nameof(Lesson.Textbook))]
|
||||
public ICollection<Lesson> Lessons { get; set; }
|
||||
public virtual ICollection<Lesson> Lessons { get; set; }
|
||||
|
||||
public Textbook()
|
||||
{
|
||||
|
||||
@@ -3,47 +3,57 @@ using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace Entities.Contracts
|
||||
{
|
||||
public enum UserRoles
|
||||
{
|
||||
Student,
|
||||
Teacher,
|
||||
Administrator
|
||||
}
|
||||
|
||||
public class User : IdentityUser<Guid>
|
||||
{
|
||||
public string? RefreshToken { get; set; }
|
||||
|
||||
public DateTime? RefreshTokenExpiryTime { get; set; }
|
||||
public string? Address { get; set; }
|
||||
|
||||
public string? HomeAddress { get; set; }
|
||||
|
||||
public string? DisplayName { get; set; }
|
||||
public SubjectAreaEnum SubjectArea { get; set; } = SubjectAreaEnum.Unknown;
|
||||
|
||||
public UserRoles? Role { get; set; }
|
||||
|
||||
public Guid? TeachSubjectId { get; set; }
|
||||
[ForeignKey(nameof(TeachSubjectId))]
|
||||
public virtual Subject? TeachSubject { get; set; }
|
||||
|
||||
[Column("deleted")]
|
||||
public bool IsDeleted { get; set; }
|
||||
|
||||
[InverseProperty(nameof(ClassUser.User))]
|
||||
public virtual ICollection<ClassUser> UserInjoinedClass { get; set; }
|
||||
|
||||
[InverseProperty(nameof(ClassTeacher.Teacher))]
|
||||
public ICollection<ClassTeacher> TaughtClassesLink { get; set; }
|
||||
[InverseProperty(nameof(ClassStudent.Student))]
|
||||
public ICollection<ClassStudent> EnrolledClassesLink { get; set; }
|
||||
//[InverseProperty(nameof(Question.Creator))]
|
||||
//public virtual ICollection<Question> CreatedQuestions { get; set; }
|
||||
|
||||
[InverseProperty(nameof(Exam.Creator))]
|
||||
public virtual ICollection<Exam> CreatedExams { get; set; }
|
||||
|
||||
[InverseProperty(nameof(SubmissionDetail.Student))]
|
||||
public virtual ICollection<SubmissionDetail> SubmissionDetails { get; set; }
|
||||
|
||||
[InverseProperty(nameof(Submission.Student))]
|
||||
public virtual ICollection<Submission> StudentSubmissions { get; set; }
|
||||
|
||||
[InverseProperty(nameof(Submission.Grader))]
|
||||
public virtual ICollection<Submission> GradedSubmissions { get; set; }
|
||||
|
||||
public ICollection<Question> CreatedQuestions { get; set; }
|
||||
public ICollection<Assignment> CreatedAssignments { get; set; }
|
||||
|
||||
public ICollection<SubmissionDetail> SubmissionDetails { get; set; }
|
||||
public ICollection<Submission> SubmissionsAsStudent { get; set; }
|
||||
public ICollection<Submission> GradedSubmissions { get; set; }
|
||||
|
||||
public User()
|
||||
{
|
||||
Id = Guid.NewGuid();
|
||||
SecurityStamp = Guid.NewGuid().ToString();
|
||||
|
||||
CreatedQuestions = new HashSet<Question>();
|
||||
TaughtClassesLink = new HashSet<ClassTeacher>();
|
||||
EnrolledClassesLink = new HashSet<ClassStudent>();
|
||||
CreatedAssignments = new HashSet<Assignment>();
|
||||
//CreatedQuestions = new HashSet<Question>();
|
||||
UserInjoinedClass = new HashSet<ClassUser>();
|
||||
CreatedExams = new HashSet<Exam>();
|
||||
GradedSubmissions = new HashSet<Submission>();
|
||||
SubmissionsAsStudent = new HashSet<Submission>();
|
||||
StudentSubmissions = new HashSet<Submission>();
|
||||
SubmissionDetails = new HashSet<SubmissionDetail>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user