diff --git a/grpc/handler.go b/grpc/handler.go index 7c09bb8..425088b 100644 --- a/grpc/handler.go +++ b/grpc/handler.go @@ -8,8 +8,6 @@ import ( "net/http" "net/http/cookiejar" "net/url" - "strconv" - "strings" "sync" "time" @@ -247,21 +245,32 @@ func (h *TaskHandler) getGrades(ctx context.Context, payload []byte) ([]byte, er return nil, err } - _, grades, err := parser.FetchGPA(httpClient) + var gpaSummary *pb.GpaSummary + summary, grades, err := parser.FetchGPA(httpClient) if err != nil { log.Warn("获取GPA页面失败,尝试成绩页面", "error", err) grades, err = parser.FetchGrades(httpClient, parser.ScoreTypeFinal) if err != nil { return nil, apperr.New("fetch_grades", err, "获取成绩失败") } + } else if summary != nil { + gpaSummary = &pb.GpaSummary{ + AverageGpa: summary.AverageGPA, + Rank: summary.Rank, + ExamTotalGpa: summary.ExamTotalGPA, + ExamTotalCredits: summary.ExamTotalCredits, + FailCredits: summary.FailCredits, + Semesters: summary.Semesters, + } } pbGrades := convertGrades(grades) result := &pb.GradesResultData{ - StudentId: req.Username, - Semester: req.Semester, - Grades: pbGrades, + StudentId: req.Username, + Semester: req.Semester, + Grades: pbGrades, + GpaSummary: gpaSummary, } log.Info("成绩获取成功", "grade_count", len(pbGrades)) @@ -338,20 +347,16 @@ func convertToInt32(arr []int) []int32 { func convertGrades(grades []parser.GradeEntry) []*pb.Grade { result := make([]*pb.Grade, 0, len(grades)) for _, g := range grades { - var credit float32 - if v, err := parseFloat(g.Credit); err == nil { - credit = v - } - var gradePoint float32 - if v, err := parseFloat(g.GradePoint); err == nil { - gradePoint = v - } result = append(result, &pb.Grade{ + Term: g.Term, CourseCode: g.Code, CourseName: g.Name, - Credit: credit, - Grade: g.Score, - GradePoint: gradePoint, + Nature: g.Nature, + Category: g.Category, + Credit: g.Credit, + Score: g.Score, + GradePoint: g.GradePoint, + IsExam: g.IsExam, }) } return result @@ -372,21 +377,9 @@ func convertExams(exams []parser.ExamEntry) []*pb.Exam { ExamType: examTypeStr, Date: e.Date, Time: e.Time, - Room: e.Week, - Seat: e.Weekday, + Week: e.Week, + Weekday: e.Weekday, }) } return result } - -func parseFloat(s string) (float32, error) { - s = strings.TrimSpace(s) - if s == "" || s == "-" { - return 0, fmt.Errorf("empty") - } - v, err := strconv.ParseFloat(s, 32) - if err != nil { - return 0, err - } - return float32(v), nil -} diff --git a/proto/runner/runner.pb.go b/proto/runner/runner.pb.go index ff501b4..53e154a 100644 --- a/proto/runner/runner.pb.go +++ b/proto/runner/runner.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.9 -// protoc v3.19.4 +// protoc-gen-go v1.36.11 +// protoc v7.34.1 // source: proto/runner/runner.proto package runner @@ -1209,19 +1209,105 @@ func (x *ScheduleTime) GetWeeks() []int32 { return nil } +// GpaSummary 学分绩汇总信息 +type GpaSummary struct { + state protoimpl.MessageState `protogen:"open.v1"` + AverageGpa string `protobuf:"bytes,1,opt,name=average_gpa,json=averageGpa,proto3" json:"average_gpa,omitempty"` // 平均学分绩 + Rank string `protobuf:"bytes,2,opt,name=rank,proto3" json:"rank,omitempty"` // 专业排名 + ExamTotalGpa string `protobuf:"bytes,3,opt,name=exam_total_gpa,json=examTotalGpa,proto3" json:"exam_total_gpa,omitempty"` // 考试课学分绩 + ExamTotalCredits string `protobuf:"bytes,4,opt,name=exam_total_credits,json=examTotalCredits,proto3" json:"exam_total_credits,omitempty"` // 考试课学分数 + FailCredits string `protobuf:"bytes,5,opt,name=fail_credits,json=failCredits,proto3" json:"fail_credits,omitempty"` // 考查课不及格学分 + Semesters string `protobuf:"bytes,6,opt,name=semesters,proto3" json:"semesters,omitempty"` // 计算学期数 + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GpaSummary) Reset() { + *x = GpaSummary{} + mi := &file_proto_runner_runner_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GpaSummary) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GpaSummary) ProtoMessage() {} + +func (x *GpaSummary) ProtoReflect() protoreflect.Message { + mi := &file_proto_runner_runner_proto_msgTypes[15] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GpaSummary.ProtoReflect.Descriptor instead. +func (*GpaSummary) Descriptor() ([]byte, []int) { + return file_proto_runner_runner_proto_rawDescGZIP(), []int{15} +} + +func (x *GpaSummary) GetAverageGpa() string { + if x != nil { + return x.AverageGpa + } + return "" +} + +func (x *GpaSummary) GetRank() string { + if x != nil { + return x.Rank + } + return "" +} + +func (x *GpaSummary) GetExamTotalGpa() string { + if x != nil { + return x.ExamTotalGpa + } + return "" +} + +func (x *GpaSummary) GetExamTotalCredits() string { + if x != nil { + return x.ExamTotalCredits + } + return "" +} + +func (x *GpaSummary) GetFailCredits() string { + if x != nil { + return x.FailCredits + } + return "" +} + +func (x *GpaSummary) GetSemesters() string { + if x != nil { + return x.Semesters + } + return "" +} + // GradesResultData 成绩结果数据 type GradesResultData struct { state protoimpl.MessageState `protogen:"open.v1"` - Semester string `protobuf:"bytes,1,opt,name=semester,proto3" json:"semester,omitempty"` // 学期 - StudentId string `protobuf:"bytes,2,opt,name=student_id,json=studentId,proto3" json:"student_id,omitempty"` // 学号 - Grades []*Grade `protobuf:"bytes,3,rep,name=grades,proto3" json:"grades,omitempty"` // 成绩列表 + Semester string `protobuf:"bytes,1,opt,name=semester,proto3" json:"semester,omitempty"` // 学期 + StudentId string `protobuf:"bytes,2,opt,name=student_id,json=studentId,proto3" json:"student_id,omitempty"` // 学号 + Grades []*Grade `protobuf:"bytes,3,rep,name=grades,proto3" json:"grades,omitempty"` // 成绩列表 + GpaSummary *GpaSummary `protobuf:"bytes,4,opt,name=gpa_summary,json=gpaSummary,proto3" json:"gpa_summary,omitempty"` // 学分绩汇总 (可选) unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } func (x *GradesResultData) Reset() { *x = GradesResultData{} - mi := &file_proto_runner_runner_proto_msgTypes[15] + mi := &file_proto_runner_runner_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1233,7 +1319,7 @@ func (x *GradesResultData) String() string { func (*GradesResultData) ProtoMessage() {} func (x *GradesResultData) ProtoReflect() protoreflect.Message { - mi := &file_proto_runner_runner_proto_msgTypes[15] + mi := &file_proto_runner_runner_proto_msgTypes[16] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1246,7 +1332,7 @@ func (x *GradesResultData) ProtoReflect() protoreflect.Message { // Deprecated: Use GradesResultData.ProtoReflect.Descriptor instead. func (*GradesResultData) Descriptor() ([]byte, []int) { - return file_proto_runner_runner_proto_rawDescGZIP(), []int{15} + return file_proto_runner_runner_proto_rawDescGZIP(), []int{16} } func (x *GradesResultData) GetSemester() string { @@ -1270,21 +1356,32 @@ func (x *GradesResultData) GetGrades() []*Grade { return nil } +func (x *GradesResultData) GetGpaSummary() *GpaSummary { + if x != nil { + return x.GpaSummary + } + return nil +} + // Grade 成绩信息 type Grade struct { state protoimpl.MessageState `protogen:"open.v1"` - CourseCode string `protobuf:"bytes,1,opt,name=course_code,json=courseCode,proto3" json:"course_code,omitempty"` // 课程代码 - CourseName string `protobuf:"bytes,2,opt,name=course_name,json=courseName,proto3" json:"course_name,omitempty"` // 课程名称 - Credit float32 `protobuf:"fixed32,3,opt,name=credit,proto3" json:"credit,omitempty"` // 学分 - Grade string `protobuf:"bytes,4,opt,name=grade,proto3" json:"grade,omitempty"` // 成绩 (可能是等级或分数) - GradePoint float32 `protobuf:"fixed32,5,opt,name=grade_point,json=gradePoint,proto3" json:"grade_point,omitempty"` // 绩点 + Term string `protobuf:"bytes,1,opt,name=term,proto3" json:"term,omitempty"` // 学期 + CourseCode string `protobuf:"bytes,2,opt,name=course_code,json=courseCode,proto3" json:"course_code,omitempty"` // 课程代码 + CourseName string `protobuf:"bytes,3,opt,name=course_name,json=courseName,proto3" json:"course_name,omitempty"` // 课程名称 + Nature string `protobuf:"bytes,4,opt,name=nature,proto3" json:"nature,omitempty"` // 课程性质 + Category string `protobuf:"bytes,5,opt,name=category,proto3" json:"category,omitempty"` // 课程类别 + Credit string `protobuf:"bytes,6,opt,name=credit,proto3" json:"credit,omitempty"` // 学分 + Score string `protobuf:"bytes,7,opt,name=score,proto3" json:"score,omitempty"` // 成绩 (可能是等级或分数) + GradePoint string `protobuf:"bytes,8,opt,name=grade_point,json=gradePoint,proto3" json:"grade_point,omitempty"` // 绩点 + IsExam string `protobuf:"bytes,9,opt,name=is_exam,json=isExam,proto3" json:"is_exam,omitempty"` // 是否考试课 unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } func (x *Grade) Reset() { *x = Grade{} - mi := &file_proto_runner_runner_proto_msgTypes[16] + mi := &file_proto_runner_runner_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1296,7 +1393,7 @@ func (x *Grade) String() string { func (*Grade) ProtoMessage() {} func (x *Grade) ProtoReflect() protoreflect.Message { - mi := &file_proto_runner_runner_proto_msgTypes[16] + mi := &file_proto_runner_runner_proto_msgTypes[17] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1309,7 +1406,14 @@ func (x *Grade) ProtoReflect() protoreflect.Message { // Deprecated: Use Grade.ProtoReflect.Descriptor instead. func (*Grade) Descriptor() ([]byte, []int) { - return file_proto_runner_runner_proto_rawDescGZIP(), []int{16} + return file_proto_runner_runner_proto_rawDescGZIP(), []int{17} +} + +func (x *Grade) GetTerm() string { + if x != nil { + return x.Term + } + return "" } func (x *Grade) GetCourseCode() string { @@ -1326,25 +1430,46 @@ func (x *Grade) GetCourseName() string { return "" } -func (x *Grade) GetCredit() float32 { +func (x *Grade) GetNature() string { if x != nil { - return x.Credit - } - return 0 -} - -func (x *Grade) GetGrade() string { - if x != nil { - return x.Grade + return x.Nature } return "" } -func (x *Grade) GetGradePoint() float32 { +func (x *Grade) GetCategory() string { + if x != nil { + return x.Category + } + return "" +} + +func (x *Grade) GetCredit() string { + if x != nil { + return x.Credit + } + return "" +} + +func (x *Grade) GetScore() string { + if x != nil { + return x.Score + } + return "" +} + +func (x *Grade) GetGradePoint() string { if x != nil { return x.GradePoint } - return 0 + return "" +} + +func (x *Grade) GetIsExam() string { + if x != nil { + return x.IsExam + } + return "" } // ExamsResultData 考试安排结果数据 @@ -1359,7 +1484,7 @@ type ExamsResultData struct { func (x *ExamsResultData) Reset() { *x = ExamsResultData{} - mi := &file_proto_runner_runner_proto_msgTypes[17] + mi := &file_proto_runner_runner_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1371,7 +1496,7 @@ func (x *ExamsResultData) String() string { func (*ExamsResultData) ProtoMessage() {} func (x *ExamsResultData) ProtoReflect() protoreflect.Message { - mi := &file_proto_runner_runner_proto_msgTypes[17] + mi := &file_proto_runner_runner_proto_msgTypes[18] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1384,7 +1509,7 @@ func (x *ExamsResultData) ProtoReflect() protoreflect.Message { // Deprecated: Use ExamsResultData.ProtoReflect.Descriptor instead. func (*ExamsResultData) Descriptor() ([]byte, []int) { - return file_proto_runner_runner_proto_rawDescGZIP(), []int{17} + return file_proto_runner_runner_proto_rawDescGZIP(), []int{18} } func (x *ExamsResultData) GetSemester() string { @@ -1411,20 +1536,19 @@ func (x *ExamsResultData) GetExams() []*Exam { // Exam 考试信息 type Exam struct { state protoimpl.MessageState `protogen:"open.v1"` - CourseCode string `protobuf:"bytes,1,opt,name=course_code,json=courseCode,proto3" json:"course_code,omitempty"` // 课程代码 - CourseName string `protobuf:"bytes,2,opt,name=course_name,json=courseName,proto3" json:"course_name,omitempty"` // 课程名称 - ExamType string `protobuf:"bytes,3,opt,name=exam_type,json=examType,proto3" json:"exam_type,omitempty"` // 考试类型 (期末/期中/补考) - Date string `protobuf:"bytes,4,opt,name=date,proto3" json:"date,omitempty"` // 考试日期 (YYYY-MM-DD) - Time string `protobuf:"bytes,5,opt,name=time,proto3" json:"time,omitempty"` // 考试时间 (HH:MM-HH:MM) - Room string `protobuf:"bytes,6,opt,name=room,proto3" json:"room,omitempty"` // 考场 - Seat string `protobuf:"bytes,7,opt,name=seat,proto3" json:"seat,omitempty"` // 座位号 + CourseName string `protobuf:"bytes,1,opt,name=course_name,json=courseName,proto3" json:"course_name,omitempty"` // 课程名称 + ExamType string `protobuf:"bytes,2,opt,name=exam_type,json=examType,proto3" json:"exam_type,omitempty"` // 考试类型 (期末/期中/补考) + Date string `protobuf:"bytes,3,opt,name=date,proto3" json:"date,omitempty"` // 考试日期 + Time string `protobuf:"bytes,4,opt,name=time,proto3" json:"time,omitempty"` // 考试时间 + Week string `protobuf:"bytes,5,opt,name=week,proto3" json:"week,omitempty"` // 考试周次 + Weekday string `protobuf:"bytes,6,opt,name=weekday,proto3" json:"weekday,omitempty"` // 星期几 unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } func (x *Exam) Reset() { *x = Exam{} - mi := &file_proto_runner_runner_proto_msgTypes[18] + mi := &file_proto_runner_runner_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1436,7 +1560,7 @@ func (x *Exam) String() string { func (*Exam) ProtoMessage() {} func (x *Exam) ProtoReflect() protoreflect.Message { - mi := &file_proto_runner_runner_proto_msgTypes[18] + mi := &file_proto_runner_runner_proto_msgTypes[19] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1449,14 +1573,7 @@ func (x *Exam) ProtoReflect() protoreflect.Message { // Deprecated: Use Exam.ProtoReflect.Descriptor instead. func (*Exam) Descriptor() ([]byte, []int) { - return file_proto_runner_runner_proto_rawDescGZIP(), []int{18} -} - -func (x *Exam) GetCourseCode() string { - if x != nil { - return x.CourseCode - } - return "" + return file_proto_runner_runner_proto_rawDescGZIP(), []int{19} } func (x *Exam) GetCourseName() string { @@ -1487,16 +1604,16 @@ func (x *Exam) GetTime() string { return "" } -func (x *Exam) GetRoom() string { +func (x *Exam) GetWeek() string { if x != nil { - return x.Room + return x.Week } return "" } -func (x *Exam) GetSeat() string { +func (x *Exam) GetWeekday() string { if x != nil { - return x.Seat + return x.Weekday } return "" } @@ -1517,7 +1634,7 @@ type UserInfoResultData struct { func (x *UserInfoResultData) Reset() { *x = UserInfoResultData{} - mi := &file_proto_runner_runner_proto_msgTypes[19] + mi := &file_proto_runner_runner_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1529,7 +1646,7 @@ func (x *UserInfoResultData) String() string { func (*UserInfoResultData) ProtoMessage() {} func (x *UserInfoResultData) ProtoReflect() protoreflect.Message { - mi := &file_proto_runner_runner_proto_msgTypes[19] + mi := &file_proto_runner_runner_proto_msgTypes[20] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1542,7 +1659,7 @@ func (x *UserInfoResultData) ProtoReflect() protoreflect.Message { // Deprecated: Use UserInfoResultData.ProtoReflect.Descriptor instead. func (*UserInfoResultData) Descriptor() ([]byte, []int) { - return file_proto_runner_runner_proto_rawDescGZIP(), []int{19} + return file_proto_runner_runner_proto_rawDescGZIP(), []int{20} } func (x *UserInfoResultData) GetStudentId() string { @@ -1680,36 +1797,49 @@ const file_proto_runner_runner_proto_rawDesc = "" + "\fScheduleTime\x12\x10\n" + "\x03day\x18\x01 \x01(\tR\x03day\x12\x1a\n" + "\bsections\x18\x02 \x03(\x05R\bsections\x12\x14\n" + - "\x05weeks\x18\x03 \x03(\x05R\x05weeks\"t\n" + + "\x05weeks\x18\x03 \x03(\x05R\x05weeks\"\xd6\x01\n" + + "\n" + + "GpaSummary\x12\x1f\n" + + "\vaverage_gpa\x18\x01 \x01(\tR\n" + + "averageGpa\x12\x12\n" + + "\x04rank\x18\x02 \x01(\tR\x04rank\x12$\n" + + "\x0eexam_total_gpa\x18\x03 \x01(\tR\fexamTotalGpa\x12,\n" + + "\x12exam_total_credits\x18\x04 \x01(\tR\x10examTotalCredits\x12!\n" + + "\ffail_credits\x18\x05 \x01(\tR\vfailCredits\x12\x1c\n" + + "\tsemesters\x18\x06 \x01(\tR\tsemesters\"\xa9\x01\n" + "\x10GradesResultData\x12\x1a\n" + "\bsemester\x18\x01 \x01(\tR\bsemester\x12\x1d\n" + "\n" + "student_id\x18\x02 \x01(\tR\tstudentId\x12%\n" + - "\x06grades\x18\x03 \x03(\v2\r.runner.GradeR\x06grades\"\x98\x01\n" + - "\x05Grade\x12\x1f\n" + - "\vcourse_code\x18\x01 \x01(\tR\n" + + "\x06grades\x18\x03 \x03(\v2\r.runner.GradeR\x06grades\x123\n" + + "\vgpa_summary\x18\x04 \x01(\v2\x12.runner.GpaSummaryR\n" + + "gpaSummary\"\xf9\x01\n" + + "\x05Grade\x12\x12\n" + + "\x04term\x18\x01 \x01(\tR\x04term\x12\x1f\n" + + "\vcourse_code\x18\x02 \x01(\tR\n" + "courseCode\x12\x1f\n" + - "\vcourse_name\x18\x02 \x01(\tR\n" + + "\vcourse_name\x18\x03 \x01(\tR\n" + "courseName\x12\x16\n" + - "\x06credit\x18\x03 \x01(\x02R\x06credit\x12\x14\n" + - "\x05grade\x18\x04 \x01(\tR\x05grade\x12\x1f\n" + - "\vgrade_point\x18\x05 \x01(\x02R\n" + - "gradePoint\"p\n" + + "\x06nature\x18\x04 \x01(\tR\x06nature\x12\x1a\n" + + "\bcategory\x18\x05 \x01(\tR\bcategory\x12\x16\n" + + "\x06credit\x18\x06 \x01(\tR\x06credit\x12\x14\n" + + "\x05score\x18\a \x01(\tR\x05score\x12\x1f\n" + + "\vgrade_point\x18\b \x01(\tR\n" + + "gradePoint\x12\x17\n" + + "\ais_exam\x18\t \x01(\tR\x06isExam\"p\n" + "\x0fExamsResultData\x12\x1a\n" + "\bsemester\x18\x01 \x01(\tR\bsemester\x12\x1d\n" + "\n" + "student_id\x18\x02 \x01(\tR\tstudentId\x12\"\n" + - "\x05exams\x18\x03 \x03(\v2\f.runner.ExamR\x05exams\"\xb5\x01\n" + + "\x05exams\x18\x03 \x03(\v2\f.runner.ExamR\x05exams\"\x9a\x01\n" + "\x04Exam\x12\x1f\n" + - "\vcourse_code\x18\x01 \x01(\tR\n" + - "courseCode\x12\x1f\n" + - "\vcourse_name\x18\x02 \x01(\tR\n" + + "\vcourse_name\x18\x01 \x01(\tR\n" + "courseName\x12\x1b\n" + - "\texam_type\x18\x03 \x01(\tR\bexamType\x12\x12\n" + - "\x04date\x18\x04 \x01(\tR\x04date\x12\x12\n" + - "\x04time\x18\x05 \x01(\tR\x04time\x12\x12\n" + - "\x04room\x18\x06 \x01(\tR\x04room\x12\x12\n" + - "\x04seat\x18\a \x01(\tR\x04seat\"\xc4\x01\n" + + "\texam_type\x18\x02 \x01(\tR\bexamType\x12\x12\n" + + "\x04date\x18\x03 \x01(\tR\x04date\x12\x12\n" + + "\x04time\x18\x04 \x01(\tR\x04time\x12\x12\n" + + "\x04week\x18\x05 \x01(\tR\x04week\x12\x18\n" + + "\aweekday\x18\x06 \x01(\tR\aweekday\"\xc4\x01\n" + "\x12UserInfoResultData\x12\x1d\n" + "\n" + "student_id\x18\x01 \x01(\tR\tstudentId\x12\x12\n" + @@ -1750,7 +1880,7 @@ func file_proto_runner_runner_proto_rawDescGZIP() []byte { } var file_proto_runner_runner_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_proto_runner_runner_proto_msgTypes = make([]protoimpl.MessageInfo, 21) +var file_proto_runner_runner_proto_msgTypes = make([]protoimpl.MessageInfo, 22) var file_proto_runner_runner_proto_goTypes = []any{ (TaskType)(0), // 0: runner.TaskType (TaskStatus)(0), // 1: runner.TaskStatus @@ -1769,12 +1899,13 @@ var file_proto_runner_runner_proto_goTypes = []any{ (*ScheduleResultData)(nil), // 14: runner.ScheduleResultData (*Course)(nil), // 15: runner.Course (*ScheduleTime)(nil), // 16: runner.ScheduleTime - (*GradesResultData)(nil), // 17: runner.GradesResultData - (*Grade)(nil), // 18: runner.Grade - (*ExamsResultData)(nil), // 19: runner.ExamsResultData - (*Exam)(nil), // 20: runner.Exam - (*UserInfoResultData)(nil), // 21: runner.UserInfoResultData - nil, // 22: runner.RegisterRequest.CapabilitiesEntry + (*GpaSummary)(nil), // 17: runner.GpaSummary + (*GradesResultData)(nil), // 18: runner.GradesResultData + (*Grade)(nil), // 19: runner.Grade + (*ExamsResultData)(nil), // 20: runner.ExamsResultData + (*Exam)(nil), // 21: runner.Exam + (*UserInfoResultData)(nil), // 22: runner.UserInfoResultData + nil, // 23: runner.RegisterRequest.CapabilitiesEntry } var file_proto_runner_runner_proto_depIdxs = []int32{ 3, // 0: runner.StreamMessage.register:type_name -> runner.RegisterRequest @@ -1784,20 +1915,21 @@ var file_proto_runner_runner_proto_depIdxs = []int32{ 7, // 4: runner.StreamMessage.task:type_name -> runner.Task 9, // 5: runner.StreamMessage.result:type_name -> runner.TaskResult 8, // 6: runner.StreamMessage.task_cancel:type_name -> runner.TaskCancel - 22, // 7: runner.RegisterRequest.capabilities:type_name -> runner.RegisterRequest.CapabilitiesEntry + 23, // 7: runner.RegisterRequest.capabilities:type_name -> runner.RegisterRequest.CapabilitiesEntry 0, // 8: runner.Task.type:type_name -> runner.TaskType 1, // 9: runner.TaskResult.status:type_name -> runner.TaskStatus 15, // 10: runner.ScheduleResultData.courses:type_name -> runner.Course 16, // 11: runner.Course.schedule:type_name -> runner.ScheduleTime - 18, // 12: runner.GradesResultData.grades:type_name -> runner.Grade - 20, // 13: runner.ExamsResultData.exams:type_name -> runner.Exam - 2, // 14: runner.RunnerHub.Connect:input_type -> runner.StreamMessage - 2, // 15: runner.RunnerHub.Connect:output_type -> runner.StreamMessage - 15, // [15:16] is the sub-list for method output_type - 14, // [14:15] is the sub-list for method input_type - 14, // [14:14] is the sub-list for extension type_name - 14, // [14:14] is the sub-list for extension extendee - 0, // [0:14] is the sub-list for field type_name + 19, // 12: runner.GradesResultData.grades:type_name -> runner.Grade + 17, // 13: runner.GradesResultData.gpa_summary:type_name -> runner.GpaSummary + 21, // 14: runner.ExamsResultData.exams:type_name -> runner.Exam + 2, // 15: runner.RunnerHub.Connect:input_type -> runner.StreamMessage + 2, // 16: runner.RunnerHub.Connect:output_type -> runner.StreamMessage + 16, // [16:17] is the sub-list for method output_type + 15, // [15:16] is the sub-list for method input_type + 15, // [15:15] is the sub-list for extension type_name + 15, // [15:15] is the sub-list for extension extendee + 0, // [0:15] is the sub-list for field type_name } func init() { file_proto_runner_runner_proto_init() } @@ -1820,7 +1952,7 @@ func file_proto_runner_runner_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_runner_runner_proto_rawDesc), len(file_proto_runner_runner_proto_rawDesc)), NumEnums: 2, - NumMessages: 21, + NumMessages: 22, NumExtensions: 0, NumServices: 1, }, diff --git a/proto/runner/runner.proto b/proto/runner/runner.proto index 0983f2a..415d6d7 100644 --- a/proto/runner/runner.proto +++ b/proto/runner/runner.proto @@ -178,20 +178,35 @@ message ScheduleTime { repeated int32 weeks = 3; // 周次,如 [1, 2, 3, 4, 5] } +// GpaSummary 学分绩汇总信息 +message GpaSummary { + string average_gpa = 1; // 平均学分绩 + string rank = 2; // 专业排名 + string exam_total_gpa = 3; // 考试课学分绩 + string exam_total_credits = 4; // 考试课学分数 + string fail_credits = 5; // 考查课不及格学分 + string semesters = 6; // 计算学期数 +} + // GradesResultData 成绩结果数据 message GradesResultData { string semester = 1; // 学期 string student_id = 2; // 学号 repeated Grade grades = 3; // 成绩列表 + GpaSummary gpa_summary = 4; // 学分绩汇总 (可选) } // Grade 成绩信息 message Grade { - string course_code = 1; // 课程代码 - string course_name = 2; // 课程名称 - float credit = 3; // 学分 - string grade = 4; // 成绩 (可能是等级或分数) - float grade_point = 5; // 绩点 + string term = 1; // 学期 + string course_code = 2; // 课程代码 + string course_name = 3; // 课程名称 + string nature = 4; // 课程性质 + string category = 5; // 课程类别 + string credit = 6; // 学分 + string score = 7; // 成绩 (可能是等级或分数) + string grade_point = 8; // 绩点 + string is_exam = 9; // 是否考试课 } // ExamsResultData 考试安排结果数据 @@ -203,13 +218,12 @@ message ExamsResultData { // Exam 考试信息 message Exam { - string course_code = 1; // 课程代码 - string course_name = 2; // 课程名称 - string exam_type = 3; // 考试类型 (期末/期中/补考) - string date = 4; // 考试日期 (YYYY-MM-DD) - string time = 5; // 考试时间 (HH:MM-HH:MM) - string room = 6; // 考场 - string seat = 7; // 座位号 + string course_name = 1; // 课程名称 + string exam_type = 2; // 考试类型 (期末/期中/补考) + string date = 3; // 考试日期 + string time = 4; // 考试时间 + string week = 5; // 考试周次 + string weekday = 6; // 星期几 } // UserInfoResultData 用户信息结果数据 diff --git a/proto/runner/runner_grpc.pb.go b/proto/runner/runner_grpc.pb.go index 7c1863e..3adf82f 100644 --- a/proto/runner/runner_grpc.pb.go +++ b/proto/runner/runner_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: -// - protoc-gen-go-grpc v1.5.1 -// - protoc v3.19.4 +// - protoc-gen-go-grpc v1.6.1 +// - protoc v7.34.1 // source: proto/runner/runner.proto package runner @@ -76,7 +76,7 @@ type RunnerHubServer interface { type UnimplementedRunnerHubServer struct{} func (UnimplementedRunnerHubServer) Connect(grpc.BidiStreamingServer[StreamMessage, StreamMessage]) error { - return status.Errorf(codes.Unimplemented, "method Connect not implemented") + return status.Error(codes.Unimplemented, "method Connect not implemented") } func (UnimplementedRunnerHubServer) mustEmbedUnimplementedRunnerHubServer() {} func (UnimplementedRunnerHubServer) testEmbeddedByValue() {} @@ -89,7 +89,7 @@ type UnsafeRunnerHubServer interface { } func RegisterRunnerHubServer(s grpc.ServiceRegistrar, srv RunnerHubServer) { - // If the following call pancis, it indicates UnimplementedRunnerHubServer was + // If the following call panics, it indicates UnimplementedRunnerHubServer was // embedded by pointer and is nil. This will cause panics if an // unimplemented method is ever invoked, so we test this at initialization // time to prevent it from happening at runtime later due to I/O.