diff --git a/src/lib/schema/ClassSchedule.go b/src/lib/schema/ClassSchedule.go new file mode 100644 index 0000000..c2c0aff --- /dev/null +++ b/src/lib/schema/ClassSchedule.go @@ -0,0 +1,18 @@ +package schema + +type Visibility string + +const ( + PRIVATE Visibility = "private" + FRIENDSONLY Visibility = "friendsOnly" + LINKONLY Visibility = "linkOnly" + PUBLIC Visibility = "public" +) + +type ClassSchedule struct { + Name string `json:"Name"` + Year int `json:"Year" binding:"required"` + Semester int `json:"Semester" binding:"required"` + Visibility Visibility `json:"Visibility" binding:"required,oneof=private friendsOnly linkOnly public"` + Courses []string `json:"Courses" binding:"dive"` +} diff --git a/src/lib/schema/ClassSchedule.ts b/src/lib/schema/ClassSchedule.ts deleted file mode 100644 index 2ed5f3c..0000000 --- a/src/lib/schema/ClassSchedule.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { z } from 'zod'; - -export const route = (classScheduleId: string) => `/classSchedule/${classScheduleId}`; - -export const ClassSchedule = z.object({ - uuid: z.uuid().describe('Unique identifier for the class schedule'), - name: z.string().min(1).max(64).describe('Name of the class schedule').optional(), // if it is undefined, set in frontend - year: z.number().describe('Academic year'), - semester: z.number().describe('Semester'), - visibility: z.enum(['private', "friendsOnly", "linkOnly", 'public']).describe('Visibility of the class schedule').default('private'), - courses: z.array(z.uuid()).describe('Array of course UUIDs').default([]), -}); - -export type ClassSchedule = z.infer; diff --git a/src/lib/schema/Course.go b/src/lib/schema/Course.go new file mode 100644 index 0000000..86e29b6 --- /dev/null +++ b/src/lib/schema/Course.go @@ -0,0 +1,50 @@ +package schema + +import "regexp" + +type CourseCategory string + +const ( + COMPULSORY CourseCategory = "Compulsory" + ELECTIVE CourseCategory = "Elective" + GENERAL CourseCategory = "General" + PE CourseCategory = "PE" + MILITARY CourseCategory = "Military" + TEACHEREDUCATION CourseCategory = "TeacherEducation" + OTHER CourseCategory = "Other" +) + +type CourseTime struct { + Start string `json:"Start" binding:"required"` + End string `json:"End" binding:"required"` +} + +type Course struct { + CourseClassroom string `json:"CourseClassroom" binding:"required,min=0,max=16"` + CourseYear int `json:"CourseYear" binding:"required"` + CourseSemester int `json:"CourseSemester" binding:"required"` + CourseCredit int `json:"CourseCredit" binding:"required"` + CourseNumber string `json:"CourseNumber" binding:"omitempty,min=1,max=16"` + CourseNameZh string `json:"CourseNameZh" binding:"omitempty,min=1,max=32"` + CourseNameEn string `json:"CourseNameEn" binding:"omitempty,min=1,max=128"` + CourseProvider []string `json:"CourseProvider" binding:"dive,min=1,max=64"` + CourseDepartment []string `json:"CourseDepartment" binding:"dive,min=1,max=64"` + CourseTime []CourseTime `json:"CourseTime" binding:"dive"` + Emi bool `json:"Emi"` + CourseCategory CourseCategory `json:"CourseCategory" binding:"required,oneof=Compulsory Elective General PE Military TeacherEducation Other"` + CourseStudentCount int `json:"CourseStudentCount" binding:"required,gte=0"` + CourseArea []string `json:"CourseArea" binding:"dive,min=1,max=64"` // for General Education or maybe can add Elective too + Url string `json:"Url" binding:"omitempty,url"` + Others string `json:"Others" binding:"omitempty,min=1,max=1024"` + Exist bool `json:"Exist"` // bool can't use binding:"required" +} + +func CourseTimeRegexCheck(course Course) bool { + re := regexp.MustCompile(`^(Mon|Tue|Wed|Thu|Fri|Sat|Sun)-([01]\d|2[0-3]):([0-5]\d)$`) + for _, ct := range course.CourseTime { + if !re.MatchString(ct.Start) || !re.MatchString(ct.End) { + return false + } + } + return true +} diff --git a/src/lib/schema/Course.ts b/src/lib/schema/Course.ts deleted file mode 100644 index 07ab647..0000000 --- a/src/lib/schema/Course.ts +++ /dev/null @@ -1,32 +0,0 @@ - -import { z } from 'zod'; - -export const route = (courseId: string) => `/course/${courseId}`; - -export const CourseSchema = z.object({ - uuid: z.uuid().describe('Unique identifier for the course'), - course_classroom: z.string().min(0).max(16).describe('Classroom location'), // can be empty "" string - course_year: z.number().describe('Academic year'), - course_semester: z.number().describe('Semester'), - course_credit: z.number().describe('Course credit'), - course_number: z.string().min(1).max(16).describe('Course number').optional(), - course_name_zh: z.string().min(1).max(32).describe('Course name in Chinese').optional(), - course_name_en: z.string().min(1).max(128).describe('Course name in English').optional(), - course_provider: z.array(z.string().min(1).max(64)).describe('Course provider').optional(), - course_department: z.string().min(1).max(32).describe('Course department'), - course_time: z.array( - z.object({ - start: z.string().regex(/^(Mon|Tue|Wed|Thu|Fri|Sat|Sun)-([01]\d|2[0-3]):([0-5]\d)$/).describe('Start time in format -: ex: Mon-09:00'), - end: z.string().regex(/^(Mon|Tue|Wed|Thu|Fri|Sat|Sun)-([01]\d|2[0-3]):([0-5]\d)$/).describe('End time in format -: ex: Mon-10:00') - }) - ).describe('Course time').default([]), // [] is also valid - update_at: z.string().regex(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?([+-]\d{2}:\d{2}|Z)$/).describe('Last update time in ISO 8601 format'), - emi: z.boolean().describe('Whether the course is EMI (English as Medium of Instruction)').default(false), - course_category: z.enum(["Compulsory", "Elective", "GeneralEducation", "PE", "MilitaryTraining", "TeacherEducation", "Other"]).describe('Course category').default("Other"), - course_student_count: z.number().describe('Number of students enrolled'), - url: z.url().min(1).max(2048).describe('Course URL').optional(), - others: z.string().min(1).max(1024).describe('Other information').optional(), - exist: z.boolean().describe('Whether the course still exists').default(true) -}); - -export type Course = z.infer; \ No newline at end of file