From 9356cb68768da736fee346a31cc436516aede38d Mon Sep 17 00:00:00 2001 From: lan Date: Sun, 31 May 2026 21:29:45 +0800 Subject: [PATCH] feat(runner): implement empty classroom sync functionality Add support for fetching and synchronizing empty classroom data. This includes new protobuf definitions for task payloads and results, database models, repository, service, and HTTP handlers. - Add `TASK_TYPE_GET_EMPTY_CLASSROOM` to `TaskType` enum - Implement `EmptyClassroom` model and auto-migration - Add `EmptyClassroomHandler` with `GET` and `POST /sync` routes - Implement `EmptyClassroomSyncService` and `EmptyClassroomRepository` - Update dependency injection with wire sets --- internal/handler/empty_classroom_handler.go | 87 + internal/model/empty_classroom.go | 26 + internal/model/init.go | 1 + internal/repository/empty_classroom_repo.go | 41 + internal/router/router.go | 13 + .../service/empty_classroom_sync_service.go | 135 + internal/wire/handler.go | 1 + internal/wire/repository.go | 1 + internal/wire/service.go | 10 + proto/runner/proto/runner/runner.pb.go | 2229 +++++++++++++++++ proto/runner/proto/runner/runner_grpc.pb.go | 125 + proto/runner/runner.pb.go | 358 ++- proto/runner/runner.proto | 28 + 13 files changed, 3007 insertions(+), 48 deletions(-) create mode 100644 internal/handler/empty_classroom_handler.go create mode 100644 internal/model/empty_classroom.go create mode 100644 internal/repository/empty_classroom_repo.go create mode 100644 internal/service/empty_classroom_sync_service.go create mode 100644 proto/runner/proto/runner/runner.pb.go create mode 100644 proto/runner/proto/runner/runner_grpc.pb.go diff --git a/internal/handler/empty_classroom_handler.go b/internal/handler/empty_classroom_handler.go new file mode 100644 index 0000000..59adda3 --- /dev/null +++ b/internal/handler/empty_classroom_handler.go @@ -0,0 +1,87 @@ +package handler + +import ( + "github.com/gin-gonic/gin" + + "with_you/internal/pkg/response" + "with_you/internal/repository" + "with_you/internal/service" +) + +type EmptyClassroomHandler struct { + classroomSyncService service.EmptyClassroomSyncService + classroomRepo repository.EmptyClassroomRepository +} + +func NewEmptyClassroomHandler( + classroomSyncService service.EmptyClassroomSyncService, + classroomRepo repository.EmptyClassroomRepository, +) *EmptyClassroomHandler { + return &EmptyClassroomHandler{ + classroomSyncService: classroomSyncService, + classroomRepo: classroomRepo, + } +} + +type syncEmptyClassroomsRequest struct { + Username string `json:"username" binding:"required"` + Password string `json:"password" binding:"required"` + Semester string `json:"semester"` + WeekStart string `json:"week_start"` + WeekEnd string `json:"week_end"` + CampusCode string `json:"campus_code"` +} + +func (h *EmptyClassroomHandler) SyncEmptyClassrooms(c *gin.Context) { + userID := c.GetString("user_id") + if userID == "" { + response.Unauthorized(c, "") + return + } + + var req syncEmptyClassroomsRequest + if err := c.ShouldBindJSON(&req); err != nil { + response.BadRequest(c, "invalid request: "+err.Error()) + return + } + + result, err := h.classroomSyncService.SyncUserEmptyClassrooms(c.Request.Context(), userID, &service.SyncEmptyClassroomsRequest{ + Username: req.Username, + Password: req.Password, + Semester: req.Semester, + WeekStart: req.WeekStart, + WeekEnd: req.WeekEnd, + CampusCode: req.CampusCode, + }) + if err != nil { + response.HandleError(c, err, "failed to sync empty classrooms") + return + } + + if !result.Success { + response.Success(c, result) + return + } + response.SuccessWithMessage(c, result.Message, result) +} + +func (h *EmptyClassroomHandler) ListEmptyClassrooms(c *gin.Context) { + userID := c.GetString("user_id") + if userID == "" { + response.Unauthorized(c, "") + return + } + semester := c.Query("semester") + if semester == "" { + response.BadRequest(c, "semester is required") + return + } + + classrooms, err := h.classroomRepo.ListByUserAndSemester(userID, semester) + if err != nil { + response.HandleError(c, err, "failed to list empty classrooms") + return + } + + response.Success(c, gin.H{"classrooms": classrooms}) +} diff --git a/internal/model/empty_classroom.go b/internal/model/empty_classroom.go new file mode 100644 index 0000000..182248e --- /dev/null +++ b/internal/model/empty_classroom.go @@ -0,0 +1,26 @@ +package model + +import ( + "time" + + "gorm.io/gorm" +) + +type EmptyClassroom struct { + ID string `json:"id" gorm:"type:varchar(36);primaryKey"` + UserID string `json:"user_id" gorm:"type:varchar(36);index;not null"` + Semester string `json:"semester" gorm:"type:varchar(30);not null"` + Classroom string `json:"classroom" gorm:"type:varchar(60);not null"` + Weekday string `json:"weekday" gorm:"type:varchar(100)"` + Periods string `json:"periods" gorm:"type:text"` + Weeks string `json:"weeks" gorm:"type:varchar(30)"` + CreatedAt time.Time + UpdatedAt time.Time +} + +func (e *EmptyClassroom) BeforeCreate(tx *gorm.DB) error { + SetUUIDIfEmpty(&e.ID) + return nil +} + +func (EmptyClassroom) TableName() string { return "empty_classrooms" } diff --git a/internal/model/init.go b/internal/model/init.go index 712e0a3..ab81ff9 100644 --- a/internal/model/init.go +++ b/internal/model/init.go @@ -193,6 +193,7 @@ func autoMigrate(db *gorm.DB) error { &Grade{}, &GpaSummary{}, &Exam{}, + &EmptyClassroom{}, // 用户活跃相关 &UserActiveLog{}, diff --git a/internal/repository/empty_classroom_repo.go b/internal/repository/empty_classroom_repo.go new file mode 100644 index 0000000..d355e2b --- /dev/null +++ b/internal/repository/empty_classroom_repo.go @@ -0,0 +1,41 @@ +package repository + +import ( + "context" + + "with_you/internal/model" + + "gorm.io/gorm" +) + +type EmptyClassroomRepository interface { + ListByUserAndSemester(userID, semester string) ([]*model.EmptyClassroom, error) + DeleteByUserAndSemester(ctx context.Context, userID, semester string) error + BatchCreate(ctx context.Context, classrooms []*model.EmptyClassroom) error +} + +type emptyClassroomRepository struct { + db *gorm.DB +} + +func NewEmptyClassroomRepository(db *gorm.DB) EmptyClassroomRepository { + return &emptyClassroomRepository{db: db} +} + +func (r *emptyClassroomRepository) ListByUserAndSemester(userID, semester string) ([]*model.EmptyClassroom, error) { + var classrooms []*model.EmptyClassroom + err := r.db.Where("user_id = ? AND semester = ?", userID, semester). + Order("classroom ASC, weekday ASC"). + Find(&classrooms).Error + return classrooms, err +} + +func (r *emptyClassroomRepository) DeleteByUserAndSemester(ctx context.Context, userID, semester string) error { + return r.db.WithContext(ctx). + Where("user_id = ? AND semester = ?", userID, semester). + Delete(&model.EmptyClassroom{}).Error +} + +func (r *emptyClassroomRepository) BatchCreate(ctx context.Context, classrooms []*model.EmptyClassroom) error { + return r.db.WithContext(ctx).CreateInBatches(classrooms, 100).Error +} diff --git a/internal/router/router.go b/internal/router/router.go index c4f57ac..2da1412 100644 --- a/internal/router/router.go +++ b/internal/router/router.go @@ -28,6 +28,7 @@ type RouterDeps struct { ScheduleHandler *handler.ScheduleHandler GradeHandler *handler.GradeHandler ExamHandler *handler.ExamHandler + EmptyClassroomHandler *handler.EmptyClassroomHandler RoleHandler *handler.RoleHandler AdminUserHandler *handler.AdminUserHandler AdminPostHandler *handler.AdminPostHandler @@ -71,6 +72,7 @@ type Router struct { scheduleHandler *handler.ScheduleHandler gradeHandler *handler.GradeHandler examHandler *handler.ExamHandler + emptyClassroomHandler *handler.EmptyClassroomHandler roleHandler *handler.RoleHandler adminUserHandler *handler.AdminUserHandler adminPostHandler *handler.AdminPostHandler @@ -117,6 +119,7 @@ func New(deps RouterDeps) *Router { scheduleHandler: deps.ScheduleHandler, gradeHandler: deps.GradeHandler, examHandler: deps.ExamHandler, + emptyClassroomHandler: deps.EmptyClassroomHandler, roleHandler: deps.RoleHandler, adminUserHandler: deps.AdminUserHandler, adminPostHandler: deps.AdminPostHandler, @@ -372,6 +375,16 @@ func (r *Router) setupRoutes() { } } + // 空教室路由 + if r.emptyClassroomHandler != nil { + classrooms := v1.Group("/classrooms") + classrooms.Use(authMiddleware) + { + classrooms.GET("", r.emptyClassroomHandler.ListEmptyClassrooms) + classrooms.POST("/sync", r.emptyClassroomHandler.SyncEmptyClassrooms) + } + } + // 学习资料路由(公开) if r.materialHandler != nil { materials := v1.Group("/materials") diff --git a/internal/service/empty_classroom_sync_service.go b/internal/service/empty_classroom_sync_service.go new file mode 100644 index 0000000..e45446b --- /dev/null +++ b/internal/service/empty_classroom_sync_service.go @@ -0,0 +1,135 @@ +package service + +import ( + "context" + "encoding/json" + "fmt" + + "with_you/internal/grpc/runner" + "with_you/internal/model" + "with_you/internal/repository" + pb "with_you/proto/runner" + + "github.com/google/uuid" + "go.uber.org/zap" +) + +type SyncEmptyClassroomsRequest struct { + Username string `json:"username" binding:"required"` + Password string `json:"password" binding:"required"` + Semester string `json:"semester"` + WeekStart string `json:"week_start"` + WeekEnd string `json:"week_end"` + CampusCode string `json:"campus_code"` +} + +type SyncEmptyClassroomsResult struct { + Success bool `json:"success"` + Message string `json:"message"` + SyncedCount int `json:"synced_count"` + ErrorMessage string `json:"error_message,omitempty"` +} + +type EmptyClassroomSyncService interface { + SyncUserEmptyClassrooms(ctx context.Context, userID string, req *SyncEmptyClassroomsRequest) (*SyncEmptyClassroomsResult, error) +} + +type emptyClassroomSyncService struct { + taskManager *runner.TaskManager + classroomRepo repository.EmptyClassroomRepository + logger *zap.Logger +} + +func NewEmptyClassroomSyncService( + taskManager *runner.TaskManager, + classroomRepo repository.EmptyClassroomRepository, + logger *zap.Logger, +) EmptyClassroomSyncService { + return &emptyClassroomSyncService{ + taskManager: taskManager, + classroomRepo: classroomRepo, + logger: logger, + } +} + +func (s *emptyClassroomSyncService) SyncUserEmptyClassrooms(ctx context.Context, userID string, req *SyncEmptyClassroomsRequest) (*SyncEmptyClassroomsResult, error) { + payload := &pb.GetEmptyClassroomPayload{ + Username: req.Username, + Password: req.Password, + Semester: req.Semester, + WeekStart: req.WeekStart, + WeekEnd: req.WeekEnd, + CampusCode: req.CampusCode, + } + + taskResult, err := s.taskManager.SubmitTaskSync(ctx, pb.TaskType_TASK_TYPE_GET_EMPTY_CLASSROOM, payload) + if err != nil { + s.logger.Error("failed to submit empty classroom sync task", + zap.String("user_id", userID), + zap.Error(err)) + return nil, fmt.Errorf("failed to submit task: %w", err) + } + + if taskResult.Status != pb.TaskStatus_TASK_STATUS_SUCCESS { + return &SyncEmptyClassroomsResult{ + Success: false, + Message: "空教室查询失败", + ErrorMessage: taskResult.ErrorMessage, + }, nil + } + + var resultData pb.EmptyClassroomResultData + if err := json.Unmarshal(taskResult.Data, &resultData); err != nil { + s.logger.Error("failed to parse empty classroom result", + zap.String("user_id", userID), + zap.Error(err)) + return nil, fmt.Errorf("failed to parse result: %w", err) + } + + classrooms := s.convertClassrooms(userID, &resultData) + if err := s.saveClassrooms(ctx, userID, resultData.Semester, classrooms); err != nil { + s.logger.Error("failed to save empty classrooms", + zap.String("user_id", userID), + zap.Error(err)) + return nil, fmt.Errorf("failed to save classrooms: %w", err) + } + + s.logger.Info("empty classrooms sync completed", + zap.String("user_id", userID), + zap.Int("classroom_count", len(classrooms))) + + return &SyncEmptyClassroomsResult{ + Success: true, + Message: "空教室查询成功", + SyncedCount: len(classrooms), + }, nil +} + +func (s *emptyClassroomSyncService) convertClassrooms(userID string, data *pb.EmptyClassroomResultData) []*model.EmptyClassroom { + classrooms := make([]*model.EmptyClassroom, 0, len(data.Classrooms)) + for _, c := range data.Classrooms { + classrooms = append(classrooms, &model.EmptyClassroom{ + ID: uuid.New().String(), + UserID: userID, + Semester: data.Semester, + Classroom: c.Classroom, + Weekday: c.Weekday, + Periods: c.Periods, + Weeks: c.Weeks, + }) + } + return classrooms +} + +func (s *emptyClassroomSyncService) saveClassrooms(ctx context.Context, userID, semester string, classrooms []*model.EmptyClassroom) error { + if err := s.classroomRepo.DeleteByUserAndSemester(ctx, userID, semester); err != nil { + return fmt.Errorf("failed to delete old classrooms: %w", err) + } + if len(classrooms) == 0 { + return nil + } + if err := s.classroomRepo.BatchCreate(ctx, classrooms); err != nil { + return fmt.Errorf("failed to create classrooms: %w", err) + } + return nil +} diff --git a/internal/wire/handler.go b/internal/wire/handler.go index 27e6ff6..24b6397 100644 --- a/internal/wire/handler.go +++ b/internal/wire/handler.go @@ -37,6 +37,7 @@ var HandlerSet = wire.NewSet( handler.NewTradeHandler, handler.NewGradeHandler, handler.NewExamHandler, + handler.NewEmptyClassroomHandler, // 需要特殊处理的 Handler ProvideUserHandler, diff --git a/internal/wire/repository.go b/internal/wire/repository.go index 7e47c60..e1884fb 100644 --- a/internal/wire/repository.go +++ b/internal/wire/repository.go @@ -26,6 +26,7 @@ var RepositorySet = wire.NewSet( repository.NewScheduleRepository, repository.NewGradeRepository, repository.NewExamRepository, + repository.NewEmptyClassroomRepository, repository.NewMaterialSubjectRepository, repository.NewMaterialFileRepository, repository.NewCallRepository, diff --git a/internal/wire/service.go b/internal/wire/service.go index 2c2fd6c..d1dc3b7 100644 --- a/internal/wire/service.go +++ b/internal/wire/service.go @@ -48,6 +48,7 @@ var ServiceSet = wire.NewSet( ProvideScheduleSyncService, ProvideGradeSyncService, ProvideExamSyncService, + ProvideEmptyClassroomSyncService, ProvideGroupService, ProvideUploadService, ProvideUserActivityService, @@ -263,6 +264,15 @@ func ProvideExamSyncService( return service.NewExamSyncService(taskManager, examRepo, logger) } +// ProvideEmptyClassroomSyncService 提供空教室同步服务 +func ProvideEmptyClassroomSyncService( + taskManager *runner.TaskManager, + classroomRepo repository.EmptyClassroomRepository, + logger *zap.Logger, +) service.EmptyClassroomSyncService { + return service.NewEmptyClassroomSyncService(taskManager, classroomRepo, logger) +} + // ProvideGroupService 提供群组服务 func ProvideGroupService( groupRepo repository.GroupRepository, diff --git a/proto/runner/proto/runner/runner.pb.go b/proto/runner/proto/runner/runner.pb.go new file mode 100644 index 0000000..dff09e9 --- /dev/null +++ b/proto/runner/proto/runner/runner.pb.go @@ -0,0 +1,2229 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11 +// protoc v7.34.1 +// source: proto/runner/runner.proto + +package runner + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// TaskType 任务类型枚举 +type TaskType int32 + +const ( + TaskType_TASK_TYPE_UNKNOWN TaskType = 0 // 未知类型 + TaskType_TASK_TYPE_LOGIN TaskType = 1 // 登录验证 + TaskType_TASK_TYPE_GET_SCHEDULE TaskType = 2 // 获取课表 + TaskType_TASK_TYPE_GET_GRADES TaskType = 3 // 获取成绩 + TaskType_TASK_TYPE_GET_EXAMS TaskType = 4 // 获取考试安排 + TaskType_TASK_TYPE_GET_USER_INFO TaskType = 5 // 获取用户信息 + TaskType_TASK_TYPE_GET_EMPTY_CLASSROOM TaskType = 6 // 获取空教室 +) + +// Enum value maps for TaskType. +var ( + TaskType_name = map[int32]string{ + 0: "TASK_TYPE_UNKNOWN", + 1: "TASK_TYPE_LOGIN", + 2: "TASK_TYPE_GET_SCHEDULE", + 3: "TASK_TYPE_GET_GRADES", + 4: "TASK_TYPE_GET_EXAMS", + 5: "TASK_TYPE_GET_USER_INFO", + 6: "TASK_TYPE_GET_EMPTY_CLASSROOM", + } + TaskType_value = map[string]int32{ + "TASK_TYPE_UNKNOWN": 0, + "TASK_TYPE_LOGIN": 1, + "TASK_TYPE_GET_SCHEDULE": 2, + "TASK_TYPE_GET_GRADES": 3, + "TASK_TYPE_GET_EXAMS": 4, + "TASK_TYPE_GET_USER_INFO": 5, + "TASK_TYPE_GET_EMPTY_CLASSROOM": 6, + } +) + +func (x TaskType) Enum() *TaskType { + p := new(TaskType) + *p = x + return p +} + +func (x TaskType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (TaskType) Descriptor() protoreflect.EnumDescriptor { + return file_proto_runner_runner_proto_enumTypes[0].Descriptor() +} + +func (TaskType) Type() protoreflect.EnumType { + return &file_proto_runner_runner_proto_enumTypes[0] +} + +func (x TaskType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use TaskType.Descriptor instead. +func (TaskType) EnumDescriptor() ([]byte, []int) { + return file_proto_runner_runner_proto_rawDescGZIP(), []int{0} +} + +// TaskStatus 任务状态枚举 +type TaskStatus int32 + +const ( + TaskStatus_TASK_STATUS_UNKNOWN TaskStatus = 0 // 未知状态 + TaskStatus_TASK_STATUS_SUCCESS TaskStatus = 1 // 成功 + TaskStatus_TASK_STATUS_FAILED TaskStatus = 2 // 失败 + TaskStatus_TASK_STATUS_TIMEOUT TaskStatus = 3 // 超时 + TaskStatus_TASK_STATUS_CANCELLED TaskStatus = 4 // 已取消 +) + +// Enum value maps for TaskStatus. +var ( + TaskStatus_name = map[int32]string{ + 0: "TASK_STATUS_UNKNOWN", + 1: "TASK_STATUS_SUCCESS", + 2: "TASK_STATUS_FAILED", + 3: "TASK_STATUS_TIMEOUT", + 4: "TASK_STATUS_CANCELLED", + } + TaskStatus_value = map[string]int32{ + "TASK_STATUS_UNKNOWN": 0, + "TASK_STATUS_SUCCESS": 1, + "TASK_STATUS_FAILED": 2, + "TASK_STATUS_TIMEOUT": 3, + "TASK_STATUS_CANCELLED": 4, + } +) + +func (x TaskStatus) Enum() *TaskStatus { + p := new(TaskStatus) + *p = x + return p +} + +func (x TaskStatus) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (TaskStatus) Descriptor() protoreflect.EnumDescriptor { + return file_proto_runner_runner_proto_enumTypes[1].Descriptor() +} + +func (TaskStatus) Type() protoreflect.EnumType { + return &file_proto_runner_runner_proto_enumTypes[1] +} + +func (x TaskStatus) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use TaskStatus.Descriptor instead. +func (TaskStatus) EnumDescriptor() ([]byte, []int) { + return file_proto_runner_runner_proto_rawDescGZIP(), []int{1} +} + +// StreamMessage 双向流消息包装 +type StreamMessage struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Types that are valid to be assigned to Message: + // + // *StreamMessage_Register + // *StreamMessage_RegisterResponse + // *StreamMessage_Heartbeat + // *StreamMessage_HeartbeatAck + // *StreamMessage_Task + // *StreamMessage_Result + // *StreamMessage_TaskCancel + Message isStreamMessage_Message `protobuf_oneof:"message"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *StreamMessage) Reset() { + *x = StreamMessage{} + mi := &file_proto_runner_runner_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *StreamMessage) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StreamMessage) ProtoMessage() {} + +func (x *StreamMessage) ProtoReflect() protoreflect.Message { + mi := &file_proto_runner_runner_proto_msgTypes[0] + 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 StreamMessage.ProtoReflect.Descriptor instead. +func (*StreamMessage) Descriptor() ([]byte, []int) { + return file_proto_runner_runner_proto_rawDescGZIP(), []int{0} +} + +func (x *StreamMessage) GetMessage() isStreamMessage_Message { + if x != nil { + return x.Message + } + return nil +} + +func (x *StreamMessage) GetRegister() *RegisterRequest { + if x != nil { + if x, ok := x.Message.(*StreamMessage_Register); ok { + return x.Register + } + } + return nil +} + +func (x *StreamMessage) GetRegisterResponse() *RegisterResponse { + if x != nil { + if x, ok := x.Message.(*StreamMessage_RegisterResponse); ok { + return x.RegisterResponse + } + } + return nil +} + +func (x *StreamMessage) GetHeartbeat() *Heartbeat { + if x != nil { + if x, ok := x.Message.(*StreamMessage_Heartbeat); ok { + return x.Heartbeat + } + } + return nil +} + +func (x *StreamMessage) GetHeartbeatAck() *HeartbeatAck { + if x != nil { + if x, ok := x.Message.(*StreamMessage_HeartbeatAck); ok { + return x.HeartbeatAck + } + } + return nil +} + +func (x *StreamMessage) GetTask() *Task { + if x != nil { + if x, ok := x.Message.(*StreamMessage_Task); ok { + return x.Task + } + } + return nil +} + +func (x *StreamMessage) GetResult() *TaskResult { + if x != nil { + if x, ok := x.Message.(*StreamMessage_Result); ok { + return x.Result + } + } + return nil +} + +func (x *StreamMessage) GetTaskCancel() *TaskCancel { + if x != nil { + if x, ok := x.Message.(*StreamMessage_TaskCancel); ok { + return x.TaskCancel + } + } + return nil +} + +type isStreamMessage_Message interface { + isStreamMessage_Message() +} + +type StreamMessage_Register struct { + Register *RegisterRequest `protobuf:"bytes,1,opt,name=register,proto3,oneof"` // Runner 注册请求 +} + +type StreamMessage_RegisterResponse struct { + RegisterResponse *RegisterResponse `protobuf:"bytes,2,opt,name=register_response,json=registerResponse,proto3,oneof"` // 注册响应 +} + +type StreamMessage_Heartbeat struct { + Heartbeat *Heartbeat `protobuf:"bytes,3,opt,name=heartbeat,proto3,oneof"` // 心跳请求 +} + +type StreamMessage_HeartbeatAck struct { + HeartbeatAck *HeartbeatAck `protobuf:"bytes,4,opt,name=heartbeat_ack,json=heartbeatAck,proto3,oneof"` // 心跳响应 +} + +type StreamMessage_Task struct { + Task *Task `protobuf:"bytes,5,opt,name=task,proto3,oneof"` // 下发的任务 +} + +type StreamMessage_Result struct { + Result *TaskResult `protobuf:"bytes,6,opt,name=result,proto3,oneof"` // 任务结果 +} + +type StreamMessage_TaskCancel struct { + TaskCancel *TaskCancel `protobuf:"bytes,7,opt,name=task_cancel,json=taskCancel,proto3,oneof"` // 取消任务 +} + +func (*StreamMessage_Register) isStreamMessage_Message() {} + +func (*StreamMessage_RegisterResponse) isStreamMessage_Message() {} + +func (*StreamMessage_Heartbeat) isStreamMessage_Message() {} + +func (*StreamMessage_HeartbeatAck) isStreamMessage_Message() {} + +func (*StreamMessage_Task) isStreamMessage_Message() {} + +func (*StreamMessage_Result) isStreamMessage_Message() {} + +func (*StreamMessage_TaskCancel) isStreamMessage_Message() {} + +// RegisterRequest Runner 注册请求 +type RegisterRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + RunnerId string `protobuf:"bytes,1,opt,name=runner_id,json=runnerId,proto3" json:"runner_id,omitempty"` // Runner 唯一标识 (UUID) + Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` // Runner 版本号 + Capabilities map[string]string `protobuf:"bytes,3,rep,name=capabilities,proto3" json:"capabilities,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` // 能力标签 + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RegisterRequest) Reset() { + *x = RegisterRequest{} + mi := &file_proto_runner_runner_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RegisterRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RegisterRequest) ProtoMessage() {} + +func (x *RegisterRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_runner_runner_proto_msgTypes[1] + 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 RegisterRequest.ProtoReflect.Descriptor instead. +func (*RegisterRequest) Descriptor() ([]byte, []int) { + return file_proto_runner_runner_proto_rawDescGZIP(), []int{1} +} + +func (x *RegisterRequest) GetRunnerId() string { + if x != nil { + return x.RunnerId + } + return "" +} + +func (x *RegisterRequest) GetVersion() string { + if x != nil { + return x.Version + } + return "" +} + +func (x *RegisterRequest) GetCapabilities() map[string]string { + if x != nil { + return x.Capabilities + } + return nil +} + +// RegisterResponse 注册响应 +type RegisterResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"` // 是否成功 + SessionId string `protobuf:"bytes,2,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` // 会话ID,用于标识本次连接 + Message string `protobuf:"bytes,3,opt,name=message,proto3" json:"message,omitempty"` // 消息说明 + HeartbeatInterval int32 `protobuf:"varint,4,opt,name=heartbeat_interval,json=heartbeatInterval,proto3" json:"heartbeat_interval,omitempty"` // 心跳间隔 (秒) + TaskTimeout int32 `protobuf:"varint,5,opt,name=task_timeout,json=taskTimeout,proto3" json:"task_timeout,omitempty"` // 默认任务超时时间 (秒) + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RegisterResponse) Reset() { + *x = RegisterResponse{} + mi := &file_proto_runner_runner_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RegisterResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RegisterResponse) ProtoMessage() {} + +func (x *RegisterResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_runner_runner_proto_msgTypes[2] + 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 RegisterResponse.ProtoReflect.Descriptor instead. +func (*RegisterResponse) Descriptor() ([]byte, []int) { + return file_proto_runner_runner_proto_rawDescGZIP(), []int{2} +} + +func (x *RegisterResponse) GetSuccess() bool { + if x != nil { + return x.Success + } + return false +} + +func (x *RegisterResponse) GetSessionId() string { + if x != nil { + return x.SessionId + } + return "" +} + +func (x *RegisterResponse) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +func (x *RegisterResponse) GetHeartbeatInterval() int32 { + if x != nil { + return x.HeartbeatInterval + } + return 0 +} + +func (x *RegisterResponse) GetTaskTimeout() int32 { + if x != nil { + return x.TaskTimeout + } + return 0 +} + +// Heartbeat 心跳请求 +type Heartbeat struct { + state protoimpl.MessageState `protogen:"open.v1"` + Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // 客户端时间戳 (毫秒) + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Heartbeat) Reset() { + *x = Heartbeat{} + mi := &file_proto_runner_runner_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Heartbeat) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Heartbeat) ProtoMessage() {} + +func (x *Heartbeat) ProtoReflect() protoreflect.Message { + mi := &file_proto_runner_runner_proto_msgTypes[3] + 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 Heartbeat.ProtoReflect.Descriptor instead. +func (*Heartbeat) Descriptor() ([]byte, []int) { + return file_proto_runner_runner_proto_rawDescGZIP(), []int{3} +} + +func (x *Heartbeat) GetTimestamp() int64 { + if x != nil { + return x.Timestamp + } + return 0 +} + +// HeartbeatAck 心跳响应 +type HeartbeatAck struct { + state protoimpl.MessageState `protogen:"open.v1"` + Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // 服务端时间戳 (毫秒) + Latency int64 `protobuf:"varint,2,opt,name=latency,proto3" json:"latency,omitempty"` // 往返延迟 (毫秒) + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *HeartbeatAck) Reset() { + *x = HeartbeatAck{} + mi := &file_proto_runner_runner_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *HeartbeatAck) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HeartbeatAck) ProtoMessage() {} + +func (x *HeartbeatAck) ProtoReflect() protoreflect.Message { + mi := &file_proto_runner_runner_proto_msgTypes[4] + 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 HeartbeatAck.ProtoReflect.Descriptor instead. +func (*HeartbeatAck) Descriptor() ([]byte, []int) { + return file_proto_runner_runner_proto_rawDescGZIP(), []int{4} +} + +func (x *HeartbeatAck) GetTimestamp() int64 { + if x != nil { + return x.Timestamp + } + return 0 +} + +func (x *HeartbeatAck) GetLatency() int64 { + if x != nil { + return x.Latency + } + return 0 +} + +// Task 任务定义 +type Task struct { + state protoimpl.MessageState `protogen:"open.v1"` + TaskId string `protobuf:"bytes,1,opt,name=task_id,json=taskId,proto3" json:"task_id,omitempty"` // 任务唯一ID (UUID) + Type TaskType `protobuf:"varint,2,opt,name=type,proto3,enum=runner.TaskType" json:"type,omitempty"` // 任务类型 + CreatedAt int64 `protobuf:"varint,3,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` // 创建时间戳 (毫秒) + TimeoutSeconds int32 `protobuf:"varint,4,opt,name=timeout_seconds,json=timeoutSeconds,proto3" json:"timeout_seconds,omitempty"` // 超时时间 (秒) + Payload []byte `protobuf:"bytes,5,opt,name=payload,proto3" json:"payload,omitempty"` // 任务载荷 (JSON 编码) + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Task) Reset() { + *x = Task{} + mi := &file_proto_runner_runner_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Task) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Task) ProtoMessage() {} + +func (x *Task) ProtoReflect() protoreflect.Message { + mi := &file_proto_runner_runner_proto_msgTypes[5] + 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 Task.ProtoReflect.Descriptor instead. +func (*Task) Descriptor() ([]byte, []int) { + return file_proto_runner_runner_proto_rawDescGZIP(), []int{5} +} + +func (x *Task) GetTaskId() string { + if x != nil { + return x.TaskId + } + return "" +} + +func (x *Task) GetType() TaskType { + if x != nil { + return x.Type + } + return TaskType_TASK_TYPE_UNKNOWN +} + +func (x *Task) GetCreatedAt() int64 { + if x != nil { + return x.CreatedAt + } + return 0 +} + +func (x *Task) GetTimeoutSeconds() int32 { + if x != nil { + return x.TimeoutSeconds + } + return 0 +} + +func (x *Task) GetPayload() []byte { + if x != nil { + return x.Payload + } + return nil +} + +// TaskCancel 取消任务 +type TaskCancel struct { + state protoimpl.MessageState `protogen:"open.v1"` + TaskId string `protobuf:"bytes,1,opt,name=task_id,json=taskId,proto3" json:"task_id,omitempty"` // 要取消的任务ID + Reason string `protobuf:"bytes,2,opt,name=reason,proto3" json:"reason,omitempty"` // 取消原因 + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *TaskCancel) Reset() { + *x = TaskCancel{} + mi := &file_proto_runner_runner_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *TaskCancel) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TaskCancel) ProtoMessage() {} + +func (x *TaskCancel) ProtoReflect() protoreflect.Message { + mi := &file_proto_runner_runner_proto_msgTypes[6] + 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 TaskCancel.ProtoReflect.Descriptor instead. +func (*TaskCancel) Descriptor() ([]byte, []int) { + return file_proto_runner_runner_proto_rawDescGZIP(), []int{6} +} + +func (x *TaskCancel) GetTaskId() string { + if x != nil { + return x.TaskId + } + return "" +} + +func (x *TaskCancel) GetReason() string { + if x != nil { + return x.Reason + } + return "" +} + +// TaskResult 任务结果 +type TaskResult struct { + state protoimpl.MessageState `protogen:"open.v1"` + TaskId string `protobuf:"bytes,1,opt,name=task_id,json=taskId,proto3" json:"task_id,omitempty"` // 任务ID + Status TaskStatus `protobuf:"varint,2,opt,name=status,proto3,enum=runner.TaskStatus" json:"status,omitempty"` // 执行状态 + CompletedAt int64 `protobuf:"varint,3,opt,name=completed_at,json=completedAt,proto3" json:"completed_at,omitempty"` // 完成时间戳 (毫秒) + Data []byte `protobuf:"bytes,4,opt,name=data,proto3" json:"data,omitempty"` // 结果数据 (JSON 编码) + ErrorCode string `protobuf:"bytes,5,opt,name=error_code,json=errorCode,proto3" json:"error_code,omitempty"` // 错误码 + ErrorMessage string `protobuf:"bytes,6,opt,name=error_message,json=errorMessage,proto3" json:"error_message,omitempty"` // 错误消息 + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *TaskResult) Reset() { + *x = TaskResult{} + mi := &file_proto_runner_runner_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *TaskResult) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TaskResult) ProtoMessage() {} + +func (x *TaskResult) ProtoReflect() protoreflect.Message { + mi := &file_proto_runner_runner_proto_msgTypes[7] + 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 TaskResult.ProtoReflect.Descriptor instead. +func (*TaskResult) Descriptor() ([]byte, []int) { + return file_proto_runner_runner_proto_rawDescGZIP(), []int{7} +} + +func (x *TaskResult) GetTaskId() string { + if x != nil { + return x.TaskId + } + return "" +} + +func (x *TaskResult) GetStatus() TaskStatus { + if x != nil { + return x.Status + } + return TaskStatus_TASK_STATUS_UNKNOWN +} + +func (x *TaskResult) GetCompletedAt() int64 { + if x != nil { + return x.CompletedAt + } + return 0 +} + +func (x *TaskResult) GetData() []byte { + if x != nil { + return x.Data + } + return nil +} + +func (x *TaskResult) GetErrorCode() string { + if x != nil { + return x.ErrorCode + } + return "" +} + +func (x *TaskResult) GetErrorMessage() string { + if x != nil { + return x.ErrorMessage + } + return "" +} + +// LoginPayload 登录任务载荷 +type LoginPayload struct { + state protoimpl.MessageState `protogen:"open.v1"` + Username string `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty"` // 学号 + Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"` // 密码 + Twfid string `protobuf:"bytes,3,opt,name=twfid,proto3" json:"twfid,omitempty"` // 初始 Cookie (可选) + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *LoginPayload) Reset() { + *x = LoginPayload{} + mi := &file_proto_runner_runner_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *LoginPayload) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LoginPayload) ProtoMessage() {} + +func (x *LoginPayload) ProtoReflect() protoreflect.Message { + mi := &file_proto_runner_runner_proto_msgTypes[8] + 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 LoginPayload.ProtoReflect.Descriptor instead. +func (*LoginPayload) Descriptor() ([]byte, []int) { + return file_proto_runner_runner_proto_rawDescGZIP(), []int{8} +} + +func (x *LoginPayload) GetUsername() string { + if x != nil { + return x.Username + } + return "" +} + +func (x *LoginPayload) GetPassword() string { + if x != nil { + return x.Password + } + return "" +} + +func (x *LoginPayload) GetTwfid() string { + if x != nil { + return x.Twfid + } + return "" +} + +// GetSchedulePayload 获取课表任务载荷 +type GetSchedulePayload struct { + state protoimpl.MessageState `protogen:"open.v1"` + Username string `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty"` // 学号 + Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"` // 密码 + Semester string `protobuf:"bytes,3,opt,name=semester,proto3" json:"semester,omitempty"` // 学期,如 "2025-20262" + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetSchedulePayload) Reset() { + *x = GetSchedulePayload{} + mi := &file_proto_runner_runner_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetSchedulePayload) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetSchedulePayload) ProtoMessage() {} + +func (x *GetSchedulePayload) ProtoReflect() protoreflect.Message { + mi := &file_proto_runner_runner_proto_msgTypes[9] + 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 GetSchedulePayload.ProtoReflect.Descriptor instead. +func (*GetSchedulePayload) Descriptor() ([]byte, []int) { + return file_proto_runner_runner_proto_rawDescGZIP(), []int{9} +} + +func (x *GetSchedulePayload) GetUsername() string { + if x != nil { + return x.Username + } + return "" +} + +func (x *GetSchedulePayload) GetPassword() string { + if x != nil { + return x.Password + } + return "" +} + +func (x *GetSchedulePayload) GetSemester() string { + if x != nil { + return x.Semester + } + return "" +} + +// GetGradesPayload 获取成绩任务载荷 +type GetGradesPayload struct { + state protoimpl.MessageState `protogen:"open.v1"` + Username string `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty"` // 学号 + Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"` // 密码 + Semester string `protobuf:"bytes,3,opt,name=semester,proto3" json:"semester,omitempty"` // 学期 (可选,为空则获取全部) + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetGradesPayload) Reset() { + *x = GetGradesPayload{} + mi := &file_proto_runner_runner_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetGradesPayload) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetGradesPayload) ProtoMessage() {} + +func (x *GetGradesPayload) ProtoReflect() protoreflect.Message { + mi := &file_proto_runner_runner_proto_msgTypes[10] + 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 GetGradesPayload.ProtoReflect.Descriptor instead. +func (*GetGradesPayload) Descriptor() ([]byte, []int) { + return file_proto_runner_runner_proto_rawDescGZIP(), []int{10} +} + +func (x *GetGradesPayload) GetUsername() string { + if x != nil { + return x.Username + } + return "" +} + +func (x *GetGradesPayload) GetPassword() string { + if x != nil { + return x.Password + } + return "" +} + +func (x *GetGradesPayload) GetSemester() string { + if x != nil { + return x.Semester + } + return "" +} + +// GetExamsPayload 获取考试安排任务载荷 +type GetExamsPayload struct { + state protoimpl.MessageState `protogen:"open.v1"` + Username string `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty"` // 学号 + Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"` // 密码 + Semester string `protobuf:"bytes,3,opt,name=semester,proto3" json:"semester,omitempty"` // 学期 + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetExamsPayload) Reset() { + *x = GetExamsPayload{} + mi := &file_proto_runner_runner_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetExamsPayload) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetExamsPayload) ProtoMessage() {} + +func (x *GetExamsPayload) ProtoReflect() protoreflect.Message { + mi := &file_proto_runner_runner_proto_msgTypes[11] + 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 GetExamsPayload.ProtoReflect.Descriptor instead. +func (*GetExamsPayload) Descriptor() ([]byte, []int) { + return file_proto_runner_runner_proto_rawDescGZIP(), []int{11} +} + +func (x *GetExamsPayload) GetUsername() string { + if x != nil { + return x.Username + } + return "" +} + +func (x *GetExamsPayload) GetPassword() string { + if x != nil { + return x.Password + } + return "" +} + +func (x *GetExamsPayload) GetSemester() string { + if x != nil { + return x.Semester + } + return "" +} + +// ScheduleResultData 课表结果数据 +type ScheduleResultData 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"` // 学号 + StudentName string `protobuf:"bytes,3,opt,name=student_name,json=studentName,proto3" json:"student_name,omitempty"` // 学生姓名 + Courses []*Course `protobuf:"bytes,4,rep,name=courses,proto3" json:"courses,omitempty"` // 课程列表 + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ScheduleResultData) Reset() { + *x = ScheduleResultData{} + mi := &file_proto_runner_runner_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ScheduleResultData) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ScheduleResultData) ProtoMessage() {} + +func (x *ScheduleResultData) ProtoReflect() protoreflect.Message { + mi := &file_proto_runner_runner_proto_msgTypes[12] + 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 ScheduleResultData.ProtoReflect.Descriptor instead. +func (*ScheduleResultData) Descriptor() ([]byte, []int) { + return file_proto_runner_runner_proto_rawDescGZIP(), []int{12} +} + +func (x *ScheduleResultData) GetSemester() string { + if x != nil { + return x.Semester + } + return "" +} + +func (x *ScheduleResultData) GetStudentId() string { + if x != nil { + return x.StudentId + } + return "" +} + +func (x *ScheduleResultData) GetStudentName() string { + if x != nil { + return x.StudentName + } + return "" +} + +func (x *ScheduleResultData) GetCourses() []*Course { + if x != nil { + return x.Courses + } + return nil +} + +// Course 课程信息 +type Course struct { + state protoimpl.MessageState `protogen:"open.v1"` + Code string `protobuf:"bytes,1,opt,name=code,proto3" json:"code,omitempty"` // 课程代码 + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` // 课程名称 + Teacher string `protobuf:"bytes,3,opt,name=teacher,proto3" json:"teacher,omitempty"` // 授课教师 + Room string `protobuf:"bytes,4,opt,name=room,proto3" json:"room,omitempty"` // 教室 + Credit float32 `protobuf:"fixed32,5,opt,name=credit,proto3" json:"credit,omitempty"` // 学分 + Schedule []*ScheduleTime `protobuf:"bytes,6,rep,name=schedule,proto3" json:"schedule,omitempty"` // 上课时间安排 + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Course) Reset() { + *x = Course{} + mi := &file_proto_runner_runner_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Course) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Course) ProtoMessage() {} + +func (x *Course) ProtoReflect() protoreflect.Message { + mi := &file_proto_runner_runner_proto_msgTypes[13] + 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 Course.ProtoReflect.Descriptor instead. +func (*Course) Descriptor() ([]byte, []int) { + return file_proto_runner_runner_proto_rawDescGZIP(), []int{13} +} + +func (x *Course) GetCode() string { + if x != nil { + return x.Code + } + return "" +} + +func (x *Course) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Course) GetTeacher() string { + if x != nil { + return x.Teacher + } + return "" +} + +func (x *Course) GetRoom() string { + if x != nil { + return x.Room + } + return "" +} + +func (x *Course) GetCredit() float32 { + if x != nil { + return x.Credit + } + return 0 +} + +func (x *Course) GetSchedule() []*ScheduleTime { + if x != nil { + return x.Schedule + } + return nil +} + +// ScheduleTime 上课时间安排 +type ScheduleTime struct { + state protoimpl.MessageState `protogen:"open.v1"` + Day string `protobuf:"bytes,1,opt,name=day,proto3" json:"day,omitempty"` // 星期几,"0"-"6" 表示周日到周六 + Sections []int32 `protobuf:"varint,2,rep,packed,name=sections,proto3" json:"sections,omitempty"` // 节次,如 [1, 2, 3] + Weeks []int32 `protobuf:"varint,3,rep,packed,name=weeks,proto3" json:"weeks,omitempty"` // 周次,如 [1, 2, 3, 4, 5] + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ScheduleTime) Reset() { + *x = ScheduleTime{} + mi := &file_proto_runner_runner_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ScheduleTime) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ScheduleTime) ProtoMessage() {} + +func (x *ScheduleTime) ProtoReflect() protoreflect.Message { + mi := &file_proto_runner_runner_proto_msgTypes[14] + 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 ScheduleTime.ProtoReflect.Descriptor instead. +func (*ScheduleTime) Descriptor() ([]byte, []int) { + return file_proto_runner_runner_proto_rawDescGZIP(), []int{14} +} + +func (x *ScheduleTime) GetDay() string { + if x != nil { + return x.Day + } + return "" +} + +func (x *ScheduleTime) GetSections() []int32 { + if x != nil { + return x.Sections + } + return nil +} + +func (x *ScheduleTime) GetWeeks() []int32 { + if x != nil { + return x.Weeks + } + 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"` // 成绩列表 + 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[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GradesResultData) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GradesResultData) ProtoMessage() {} + +func (x *GradesResultData) ProtoReflect() protoreflect.Message { + mi := &file_proto_runner_runner_proto_msgTypes[16] + 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 GradesResultData.ProtoReflect.Descriptor instead. +func (*GradesResultData) Descriptor() ([]byte, []int) { + return file_proto_runner_runner_proto_rawDescGZIP(), []int{16} +} + +func (x *GradesResultData) GetSemester() string { + if x != nil { + return x.Semester + } + return "" +} + +func (x *GradesResultData) GetStudentId() string { + if x != nil { + return x.StudentId + } + return "" +} + +func (x *GradesResultData) GetGrades() []*Grade { + if x != nil { + return x.Grades + } + 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"` + 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[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Grade) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Grade) ProtoMessage() {} + +func (x *Grade) ProtoReflect() protoreflect.Message { + mi := &file_proto_runner_runner_proto_msgTypes[17] + 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 Grade.ProtoReflect.Descriptor instead. +func (*Grade) Descriptor() ([]byte, []int) { + 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 { + if x != nil { + return x.CourseCode + } + return "" +} + +func (x *Grade) GetCourseName() string { + if x != nil { + return x.CourseName + } + return "" +} + +func (x *Grade) GetNature() string { + if x != nil { + return x.Nature + } + return "" +} + +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 "" +} + +func (x *Grade) GetIsExam() string { + if x != nil { + return x.IsExam + } + return "" +} + +// ExamsResultData 考试安排结果数据 +type ExamsResultData 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"` // 学号 + Exams []*Exam `protobuf:"bytes,3,rep,name=exams,proto3" json:"exams,omitempty"` // 考试列表 + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ExamsResultData) Reset() { + *x = ExamsResultData{} + mi := &file_proto_runner_runner_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ExamsResultData) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExamsResultData) ProtoMessage() {} + +func (x *ExamsResultData) ProtoReflect() protoreflect.Message { + mi := &file_proto_runner_runner_proto_msgTypes[18] + 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 ExamsResultData.ProtoReflect.Descriptor instead. +func (*ExamsResultData) Descriptor() ([]byte, []int) { + return file_proto_runner_runner_proto_rawDescGZIP(), []int{18} +} + +func (x *ExamsResultData) GetSemester() string { + if x != nil { + return x.Semester + } + return "" +} + +func (x *ExamsResultData) GetStudentId() string { + if x != nil { + return x.StudentId + } + return "" +} + +func (x *ExamsResultData) GetExams() []*Exam { + if x != nil { + return x.Exams + } + return nil +} + +// Exam 考试信息 +type Exam struct { + state protoimpl.MessageState `protogen:"open.v1"` + 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[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Exam) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Exam) ProtoMessage() {} + +func (x *Exam) ProtoReflect() protoreflect.Message { + mi := &file_proto_runner_runner_proto_msgTypes[19] + 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 Exam.ProtoReflect.Descriptor instead. +func (*Exam) Descriptor() ([]byte, []int) { + return file_proto_runner_runner_proto_rawDescGZIP(), []int{19} +} + +func (x *Exam) GetCourseName() string { + if x != nil { + return x.CourseName + } + return "" +} + +func (x *Exam) GetExamType() string { + if x != nil { + return x.ExamType + } + return "" +} + +func (x *Exam) GetDate() string { + if x != nil { + return x.Date + } + return "" +} + +func (x *Exam) GetTime() string { + if x != nil { + return x.Time + } + return "" +} + +func (x *Exam) GetWeek() string { + if x != nil { + return x.Week + } + return "" +} + +func (x *Exam) GetWeekday() string { + if x != nil { + return x.Weekday + } + return "" +} + +// UserInfoResultData 用户信息结果数据 +type UserInfoResultData struct { + state protoimpl.MessageState `protogen:"open.v1"` + StudentId string `protobuf:"bytes,1,opt,name=student_id,json=studentId,proto3" json:"student_id,omitempty"` // 学号 + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` // 姓名 + Gender string `protobuf:"bytes,3,opt,name=gender,proto3" json:"gender,omitempty"` // 性别 + College string `protobuf:"bytes,4,opt,name=college,proto3" json:"college,omitempty"` // 学院 + Major string `protobuf:"bytes,5,opt,name=major,proto3" json:"major,omitempty"` // 专业 + ClassName string `protobuf:"bytes,6,opt,name=class_name,json=className,proto3" json:"class_name,omitempty"` // 班级 + Grade string `protobuf:"bytes,7,opt,name=grade,proto3" json:"grade,omitempty"` // 年级 + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UserInfoResultData) Reset() { + *x = UserInfoResultData{} + mi := &file_proto_runner_runner_proto_msgTypes[20] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UserInfoResultData) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UserInfoResultData) ProtoMessage() {} + +func (x *UserInfoResultData) ProtoReflect() protoreflect.Message { + mi := &file_proto_runner_runner_proto_msgTypes[20] + 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 UserInfoResultData.ProtoReflect.Descriptor instead. +func (*UserInfoResultData) Descriptor() ([]byte, []int) { + return file_proto_runner_runner_proto_rawDescGZIP(), []int{20} +} + +func (x *UserInfoResultData) GetStudentId() string { + if x != nil { + return x.StudentId + } + return "" +} + +func (x *UserInfoResultData) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *UserInfoResultData) GetGender() string { + if x != nil { + return x.Gender + } + return "" +} + +func (x *UserInfoResultData) GetCollege() string { + if x != nil { + return x.College + } + return "" +} + +func (x *UserInfoResultData) GetMajor() string { + if x != nil { + return x.Major + } + return "" +} + +func (x *UserInfoResultData) GetClassName() string { + if x != nil { + return x.ClassName + } + return "" +} + +func (x *UserInfoResultData) GetGrade() string { + if x != nil { + return x.Grade + } + return "" +} + +// GetEmptyClassroomPayload 获取空教室任务载荷 +type GetEmptyClassroomPayload struct { + state protoimpl.MessageState `protogen:"open.v1"` + Username string `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty"` // 学号 + Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"` // 密码 + Semester string `protobuf:"bytes,3,opt,name=semester,proto3" json:"semester,omitempty"` // 学期 + WeekStart string `protobuf:"bytes,4,opt,name=week_start,json=weekStart,proto3" json:"week_start,omitempty"` // 起始周次 + WeekEnd string `protobuf:"bytes,5,opt,name=week_end,json=weekEnd,proto3" json:"week_end,omitempty"` // 结束周次 + CampusCode string `protobuf:"bytes,6,opt,name=campus_code,json=campusCode,proto3" json:"campus_code,omitempty"` // 校区代码 + BuildingCode string `protobuf:"bytes,7,opt,name=building_code,json=buildingCode,proto3" json:"building_code,omitempty"` // 楼号代码(可选) + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetEmptyClassroomPayload) Reset() { + *x = GetEmptyClassroomPayload{} + mi := &file_proto_runner_runner_proto_msgTypes[21] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetEmptyClassroomPayload) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetEmptyClassroomPayload) ProtoMessage() {} + +func (x *GetEmptyClassroomPayload) ProtoReflect() protoreflect.Message { + mi := &file_proto_runner_runner_proto_msgTypes[21] + 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 GetEmptyClassroomPayload.ProtoReflect.Descriptor instead. +func (*GetEmptyClassroomPayload) Descriptor() ([]byte, []int) { + return file_proto_runner_runner_proto_rawDescGZIP(), []int{21} +} + +func (x *GetEmptyClassroomPayload) GetUsername() string { + if x != nil { + return x.Username + } + return "" +} + +func (x *GetEmptyClassroomPayload) GetPassword() string { + if x != nil { + return x.Password + } + return "" +} + +func (x *GetEmptyClassroomPayload) GetSemester() string { + if x != nil { + return x.Semester + } + return "" +} + +func (x *GetEmptyClassroomPayload) GetWeekStart() string { + if x != nil { + return x.WeekStart + } + return "" +} + +func (x *GetEmptyClassroomPayload) GetWeekEnd() string { + if x != nil { + return x.WeekEnd + } + return "" +} + +func (x *GetEmptyClassroomPayload) GetCampusCode() string { + if x != nil { + return x.CampusCode + } + return "" +} + +func (x *GetEmptyClassroomPayload) GetBuildingCode() string { + if x != nil { + return x.BuildingCode + } + return "" +} + +// EmptyClassroomResultData 空教室结果数据 +type EmptyClassroomResultData 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"` // 学号 + Classrooms []*EmptyClassroomEntry `protobuf:"bytes,3,rep,name=classrooms,proto3" json:"classrooms,omitempty"` // 空教室列表 + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *EmptyClassroomResultData) Reset() { + *x = EmptyClassroomResultData{} + mi := &file_proto_runner_runner_proto_msgTypes[22] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *EmptyClassroomResultData) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EmptyClassroomResultData) ProtoMessage() {} + +func (x *EmptyClassroomResultData) ProtoReflect() protoreflect.Message { + mi := &file_proto_runner_runner_proto_msgTypes[22] + 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 EmptyClassroomResultData.ProtoReflect.Descriptor instead. +func (*EmptyClassroomResultData) Descriptor() ([]byte, []int) { + return file_proto_runner_runner_proto_rawDescGZIP(), []int{22} +} + +func (x *EmptyClassroomResultData) GetSemester() string { + if x != nil { + return x.Semester + } + return "" +} + +func (x *EmptyClassroomResultData) GetStudentId() string { + if x != nil { + return x.StudentId + } + return "" +} + +func (x *EmptyClassroomResultData) GetClassrooms() []*EmptyClassroomEntry { + if x != nil { + return x.Classrooms + } + return nil +} + +// EmptyClassroomEntry 空教室条目 +type EmptyClassroomEntry struct { + state protoimpl.MessageState `protogen:"open.v1"` + Classroom string `protobuf:"bytes,1,opt,name=classroom,proto3" json:"classroom,omitempty"` // 教室名称 + Weekday string `protobuf:"bytes,2,opt,name=weekday,proto3" json:"weekday,omitempty"` // 星期几 + Periods string `protobuf:"bytes,3,opt,name=periods,proto3" json:"periods,omitempty"` // 可用节次 + Term string `protobuf:"bytes,4,opt,name=term,proto3" json:"term,omitempty"` // 学期描述 + Weeks string `protobuf:"bytes,5,opt,name=weeks,proto3" json:"weeks,omitempty"` // 周次范围 + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *EmptyClassroomEntry) Reset() { + *x = EmptyClassroomEntry{} + mi := &file_proto_runner_runner_proto_msgTypes[23] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *EmptyClassroomEntry) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EmptyClassroomEntry) ProtoMessage() {} + +func (x *EmptyClassroomEntry) ProtoReflect() protoreflect.Message { + mi := &file_proto_runner_runner_proto_msgTypes[23] + 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 EmptyClassroomEntry.ProtoReflect.Descriptor instead. +func (*EmptyClassroomEntry) Descriptor() ([]byte, []int) { + return file_proto_runner_runner_proto_rawDescGZIP(), []int{23} +} + +func (x *EmptyClassroomEntry) GetClassroom() string { + if x != nil { + return x.Classroom + } + return "" +} + +func (x *EmptyClassroomEntry) GetWeekday() string { + if x != nil { + return x.Weekday + } + return "" +} + +func (x *EmptyClassroomEntry) GetPeriods() string { + if x != nil { + return x.Periods + } + return "" +} + +func (x *EmptyClassroomEntry) GetTerm() string { + if x != nil { + return x.Term + } + return "" +} + +func (x *EmptyClassroomEntry) GetWeeks() string { + if x != nil { + return x.Weeks + } + return "" +} + +var File_proto_runner_runner_proto protoreflect.FileDescriptor + +const file_proto_runner_runner_proto_rawDesc = "" + + "\n" + + "\x19proto/runner/runner.proto\x12\x06runner\"\x93\x03\n" + + "\rStreamMessage\x125\n" + + "\bregister\x18\x01 \x01(\v2\x17.runner.RegisterRequestH\x00R\bregister\x12G\n" + + "\x11register_response\x18\x02 \x01(\v2\x18.runner.RegisterResponseH\x00R\x10registerResponse\x121\n" + + "\theartbeat\x18\x03 \x01(\v2\x11.runner.HeartbeatH\x00R\theartbeat\x12;\n" + + "\rheartbeat_ack\x18\x04 \x01(\v2\x14.runner.HeartbeatAckH\x00R\fheartbeatAck\x12\"\n" + + "\x04task\x18\x05 \x01(\v2\f.runner.TaskH\x00R\x04task\x12,\n" + + "\x06result\x18\x06 \x01(\v2\x12.runner.TaskResultH\x00R\x06result\x125\n" + + "\vtask_cancel\x18\a \x01(\v2\x12.runner.TaskCancelH\x00R\n" + + "taskCancelB\t\n" + + "\amessage\"\xd8\x01\n" + + "\x0fRegisterRequest\x12\x1b\n" + + "\trunner_id\x18\x01 \x01(\tR\brunnerId\x12\x18\n" + + "\aversion\x18\x02 \x01(\tR\aversion\x12M\n" + + "\fcapabilities\x18\x03 \x03(\v2).runner.RegisterRequest.CapabilitiesEntryR\fcapabilities\x1a?\n" + + "\x11CapabilitiesEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"\xb7\x01\n" + + "\x10RegisterResponse\x12\x18\n" + + "\asuccess\x18\x01 \x01(\bR\asuccess\x12\x1d\n" + + "\n" + + "session_id\x18\x02 \x01(\tR\tsessionId\x12\x18\n" + + "\amessage\x18\x03 \x01(\tR\amessage\x12-\n" + + "\x12heartbeat_interval\x18\x04 \x01(\x05R\x11heartbeatInterval\x12!\n" + + "\ftask_timeout\x18\x05 \x01(\x05R\vtaskTimeout\")\n" + + "\tHeartbeat\x12\x1c\n" + + "\ttimestamp\x18\x01 \x01(\x03R\ttimestamp\"F\n" + + "\fHeartbeatAck\x12\x1c\n" + + "\ttimestamp\x18\x01 \x01(\x03R\ttimestamp\x12\x18\n" + + "\alatency\x18\x02 \x01(\x03R\alatency\"\xa7\x01\n" + + "\x04Task\x12\x17\n" + + "\atask_id\x18\x01 \x01(\tR\x06taskId\x12$\n" + + "\x04type\x18\x02 \x01(\x0e2\x10.runner.TaskTypeR\x04type\x12\x1d\n" + + "\n" + + "created_at\x18\x03 \x01(\x03R\tcreatedAt\x12'\n" + + "\x0ftimeout_seconds\x18\x04 \x01(\x05R\x0etimeoutSeconds\x12\x18\n" + + "\apayload\x18\x05 \x01(\fR\apayload\"=\n" + + "\n" + + "TaskCancel\x12\x17\n" + + "\atask_id\x18\x01 \x01(\tR\x06taskId\x12\x16\n" + + "\x06reason\x18\x02 \x01(\tR\x06reason\"\xcc\x01\n" + + "\n" + + "TaskResult\x12\x17\n" + + "\atask_id\x18\x01 \x01(\tR\x06taskId\x12*\n" + + "\x06status\x18\x02 \x01(\x0e2\x12.runner.TaskStatusR\x06status\x12!\n" + + "\fcompleted_at\x18\x03 \x01(\x03R\vcompletedAt\x12\x12\n" + + "\x04data\x18\x04 \x01(\fR\x04data\x12\x1d\n" + + "\n" + + "error_code\x18\x05 \x01(\tR\terrorCode\x12#\n" + + "\rerror_message\x18\x06 \x01(\tR\ferrorMessage\"\\\n" + + "\fLoginPayload\x12\x1a\n" + + "\busername\x18\x01 \x01(\tR\busername\x12\x1a\n" + + "\bpassword\x18\x02 \x01(\tR\bpassword\x12\x14\n" + + "\x05twfid\x18\x03 \x01(\tR\x05twfid\"h\n" + + "\x12GetSchedulePayload\x12\x1a\n" + + "\busername\x18\x01 \x01(\tR\busername\x12\x1a\n" + + "\bpassword\x18\x02 \x01(\tR\bpassword\x12\x1a\n" + + "\bsemester\x18\x03 \x01(\tR\bsemester\"f\n" + + "\x10GetGradesPayload\x12\x1a\n" + + "\busername\x18\x01 \x01(\tR\busername\x12\x1a\n" + + "\bpassword\x18\x02 \x01(\tR\bpassword\x12\x1a\n" + + "\bsemester\x18\x03 \x01(\tR\bsemester\"e\n" + + "\x0fGetExamsPayload\x12\x1a\n" + + "\busername\x18\x01 \x01(\tR\busername\x12\x1a\n" + + "\bpassword\x18\x02 \x01(\tR\bpassword\x12\x1a\n" + + "\bsemester\x18\x03 \x01(\tR\bsemester\"\x9c\x01\n" + + "\x12ScheduleResultData\x12\x1a\n" + + "\bsemester\x18\x01 \x01(\tR\bsemester\x12\x1d\n" + + "\n" + + "student_id\x18\x02 \x01(\tR\tstudentId\x12!\n" + + "\fstudent_name\x18\x03 \x01(\tR\vstudentName\x12(\n" + + "\acourses\x18\x04 \x03(\v2\x0e.runner.CourseR\acourses\"\xa8\x01\n" + + "\x06Course\x12\x12\n" + + "\x04code\x18\x01 \x01(\tR\x04code\x12\x12\n" + + "\x04name\x18\x02 \x01(\tR\x04name\x12\x18\n" + + "\ateacher\x18\x03 \x01(\tR\ateacher\x12\x12\n" + + "\x04room\x18\x04 \x01(\tR\x04room\x12\x16\n" + + "\x06credit\x18\x05 \x01(\x02R\x06credit\x120\n" + + "\bschedule\x18\x06 \x03(\v2\x14.runner.ScheduleTimeR\bschedule\"R\n" + + "\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\"\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\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\x03 \x01(\tR\n" + + "courseName\x12\x16\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\"\x9a\x01\n" + + "\x04Exam\x12\x1f\n" + + "\vcourse_name\x18\x01 \x01(\tR\n" + + "courseName\x12\x1b\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" + + "\x04name\x18\x02 \x01(\tR\x04name\x12\x16\n" + + "\x06gender\x18\x03 \x01(\tR\x06gender\x12\x18\n" + + "\acollege\x18\x04 \x01(\tR\acollege\x12\x14\n" + + "\x05major\x18\x05 \x01(\tR\x05major\x12\x1d\n" + + "\n" + + "class_name\x18\x06 \x01(\tR\tclassName\x12\x14\n" + + "\x05grade\x18\a \x01(\tR\x05grade\"\xee\x01\n" + + "\x18GetEmptyClassroomPayload\x12\x1a\n" + + "\busername\x18\x01 \x01(\tR\busername\x12\x1a\n" + + "\bpassword\x18\x02 \x01(\tR\bpassword\x12\x1a\n" + + "\bsemester\x18\x03 \x01(\tR\bsemester\x12\x1d\n" + + "\n" + + "week_start\x18\x04 \x01(\tR\tweekStart\x12\x19\n" + + "\bweek_end\x18\x05 \x01(\tR\aweekEnd\x12\x1f\n" + + "\vcampus_code\x18\x06 \x01(\tR\n" + + "campusCode\x12#\n" + + "\rbuilding_code\x18\a \x01(\tR\fbuildingCode\"\x92\x01\n" + + "\x18EmptyClassroomResultData\x12\x1a\n" + + "\bsemester\x18\x01 \x01(\tR\bsemester\x12\x1d\n" + + "\n" + + "student_id\x18\x02 \x01(\tR\tstudentId\x12;\n" + + "\n" + + "classrooms\x18\x03 \x03(\v2\x1b.runner.EmptyClassroomEntryR\n" + + "classrooms\"\x91\x01\n" + + "\x13EmptyClassroomEntry\x12\x1c\n" + + "\tclassroom\x18\x01 \x01(\tR\tclassroom\x12\x18\n" + + "\aweekday\x18\x02 \x01(\tR\aweekday\x12\x18\n" + + "\aperiods\x18\x03 \x01(\tR\aperiods\x12\x12\n" + + "\x04term\x18\x04 \x01(\tR\x04term\x12\x14\n" + + "\x05weeks\x18\x05 \x01(\tR\x05weeks*\xc5\x01\n" + + "\bTaskType\x12\x15\n" + + "\x11TASK_TYPE_UNKNOWN\x10\x00\x12\x13\n" + + "\x0fTASK_TYPE_LOGIN\x10\x01\x12\x1a\n" + + "\x16TASK_TYPE_GET_SCHEDULE\x10\x02\x12\x18\n" + + "\x14TASK_TYPE_GET_GRADES\x10\x03\x12\x17\n" + + "\x13TASK_TYPE_GET_EXAMS\x10\x04\x12\x1b\n" + + "\x17TASK_TYPE_GET_USER_INFO\x10\x05\x12!\n" + + "\x1dTASK_TYPE_GET_EMPTY_CLASSROOM\x10\x06*\x8a\x01\n" + + "\n" + + "TaskStatus\x12\x17\n" + + "\x13TASK_STATUS_UNKNOWN\x10\x00\x12\x17\n" + + "\x13TASK_STATUS_SUCCESS\x10\x01\x12\x16\n" + + "\x12TASK_STATUS_FAILED\x10\x02\x12\x17\n" + + "\x13TASK_STATUS_TIMEOUT\x10\x03\x12\x19\n" + + "\x15TASK_STATUS_CANCELLED\x10\x042H\n" + + "\tRunnerHub\x12;\n" + + "\aConnect\x12\x15.runner.StreamMessage\x1a\x15.runner.StreamMessage(\x010\x01B(Z&schedule_converter/proto/runner;runnerb\x06proto3" + +var ( + file_proto_runner_runner_proto_rawDescOnce sync.Once + file_proto_runner_runner_proto_rawDescData []byte +) + +func file_proto_runner_runner_proto_rawDescGZIP() []byte { + file_proto_runner_runner_proto_rawDescOnce.Do(func() { + file_proto_runner_runner_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_proto_runner_runner_proto_rawDesc), len(file_proto_runner_runner_proto_rawDesc))) + }) + return file_proto_runner_runner_proto_rawDescData +} + +var file_proto_runner_runner_proto_enumTypes = make([]protoimpl.EnumInfo, 2) +var file_proto_runner_runner_proto_msgTypes = make([]protoimpl.MessageInfo, 25) +var file_proto_runner_runner_proto_goTypes = []any{ + (TaskType)(0), // 0: runner.TaskType + (TaskStatus)(0), // 1: runner.TaskStatus + (*StreamMessage)(nil), // 2: runner.StreamMessage + (*RegisterRequest)(nil), // 3: runner.RegisterRequest + (*RegisterResponse)(nil), // 4: runner.RegisterResponse + (*Heartbeat)(nil), // 5: runner.Heartbeat + (*HeartbeatAck)(nil), // 6: runner.HeartbeatAck + (*Task)(nil), // 7: runner.Task + (*TaskCancel)(nil), // 8: runner.TaskCancel + (*TaskResult)(nil), // 9: runner.TaskResult + (*LoginPayload)(nil), // 10: runner.LoginPayload + (*GetSchedulePayload)(nil), // 11: runner.GetSchedulePayload + (*GetGradesPayload)(nil), // 12: runner.GetGradesPayload + (*GetExamsPayload)(nil), // 13: runner.GetExamsPayload + (*ScheduleResultData)(nil), // 14: runner.ScheduleResultData + (*Course)(nil), // 15: runner.Course + (*ScheduleTime)(nil), // 16: runner.ScheduleTime + (*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 + (*GetEmptyClassroomPayload)(nil), // 23: runner.GetEmptyClassroomPayload + (*EmptyClassroomResultData)(nil), // 24: runner.EmptyClassroomResultData + (*EmptyClassroomEntry)(nil), // 25: runner.EmptyClassroomEntry + nil, // 26: runner.RegisterRequest.CapabilitiesEntry +} +var file_proto_runner_runner_proto_depIdxs = []int32{ + 3, // 0: runner.StreamMessage.register:type_name -> runner.RegisterRequest + 4, // 1: runner.StreamMessage.register_response:type_name -> runner.RegisterResponse + 5, // 2: runner.StreamMessage.heartbeat:type_name -> runner.Heartbeat + 6, // 3: runner.StreamMessage.heartbeat_ack:type_name -> runner.HeartbeatAck + 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 + 26, // 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 + 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 + 25, // 15: runner.EmptyClassroomResultData.classrooms:type_name -> runner.EmptyClassroomEntry + 2, // 16: runner.RunnerHub.Connect:input_type -> runner.StreamMessage + 2, // 17: runner.RunnerHub.Connect:output_type -> runner.StreamMessage + 17, // [17:18] is the sub-list for method output_type + 16, // [16:17] is the sub-list for method input_type + 16, // [16:16] is the sub-list for extension type_name + 16, // [16:16] is the sub-list for extension extendee + 0, // [0:16] is the sub-list for field type_name +} + +func init() { file_proto_runner_runner_proto_init() } +func file_proto_runner_runner_proto_init() { + if File_proto_runner_runner_proto != nil { + return + } + file_proto_runner_runner_proto_msgTypes[0].OneofWrappers = []any{ + (*StreamMessage_Register)(nil), + (*StreamMessage_RegisterResponse)(nil), + (*StreamMessage_Heartbeat)(nil), + (*StreamMessage_HeartbeatAck)(nil), + (*StreamMessage_Task)(nil), + (*StreamMessage_Result)(nil), + (*StreamMessage_TaskCancel)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + 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: 25, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_proto_runner_runner_proto_goTypes, + DependencyIndexes: file_proto_runner_runner_proto_depIdxs, + EnumInfos: file_proto_runner_runner_proto_enumTypes, + MessageInfos: file_proto_runner_runner_proto_msgTypes, + }.Build() + File_proto_runner_runner_proto = out.File + file_proto_runner_runner_proto_goTypes = nil + file_proto_runner_runner_proto_depIdxs = nil +} diff --git a/proto/runner/proto/runner/runner_grpc.pb.go b/proto/runner/proto/runner/runner_grpc.pb.go new file mode 100644 index 0000000..3adf82f --- /dev/null +++ b/proto/runner/proto/runner/runner_grpc.pb.go @@ -0,0 +1,125 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.6.1 +// - protoc v7.34.1 +// source: proto/runner/runner.proto + +package runner + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 + +const ( + RunnerHub_Connect_FullMethodName = "/runner.RunnerHub/Connect" +) + +// RunnerHubClient is the client API for RunnerHub service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +// +// RunnerHub 服务 - 由 Backend 服务器实现 +// Runner 作为客户端主动连接,建立双向流通信 +type RunnerHubClient interface { + // Connect 建立双向流连接 + // Runner 通过此连接注册、接收任务、返回结果 + Connect(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[StreamMessage, StreamMessage], error) +} + +type runnerHubClient struct { + cc grpc.ClientConnInterface +} + +func NewRunnerHubClient(cc grpc.ClientConnInterface) RunnerHubClient { + return &runnerHubClient{cc} +} + +func (c *runnerHubClient) Connect(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[StreamMessage, StreamMessage], error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + stream, err := c.cc.NewStream(ctx, &RunnerHub_ServiceDesc.Streams[0], RunnerHub_Connect_FullMethodName, cOpts...) + if err != nil { + return nil, err + } + x := &grpc.GenericClientStream[StreamMessage, StreamMessage]{ClientStream: stream} + return x, nil +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type RunnerHub_ConnectClient = grpc.BidiStreamingClient[StreamMessage, StreamMessage] + +// RunnerHubServer is the server API for RunnerHub service. +// All implementations must embed UnimplementedRunnerHubServer +// for forward compatibility. +// +// RunnerHub 服务 - 由 Backend 服务器实现 +// Runner 作为客户端主动连接,建立双向流通信 +type RunnerHubServer interface { + // Connect 建立双向流连接 + // Runner 通过此连接注册、接收任务、返回结果 + Connect(grpc.BidiStreamingServer[StreamMessage, StreamMessage]) error + mustEmbedUnimplementedRunnerHubServer() +} + +// UnimplementedRunnerHubServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedRunnerHubServer struct{} + +func (UnimplementedRunnerHubServer) Connect(grpc.BidiStreamingServer[StreamMessage, StreamMessage]) error { + return status.Error(codes.Unimplemented, "method Connect not implemented") +} +func (UnimplementedRunnerHubServer) mustEmbedUnimplementedRunnerHubServer() {} +func (UnimplementedRunnerHubServer) testEmbeddedByValue() {} + +// UnsafeRunnerHubServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to RunnerHubServer will +// result in compilation errors. +type UnsafeRunnerHubServer interface { + mustEmbedUnimplementedRunnerHubServer() +} + +func RegisterRunnerHubServer(s grpc.ServiceRegistrar, srv RunnerHubServer) { + // 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. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&RunnerHub_ServiceDesc, srv) +} + +func _RunnerHub_Connect_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(RunnerHubServer).Connect(&grpc.GenericServerStream[StreamMessage, StreamMessage]{ServerStream: stream}) +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type RunnerHub_ConnectServer = grpc.BidiStreamingServer[StreamMessage, StreamMessage] + +// RunnerHub_ServiceDesc is the grpc.ServiceDesc for RunnerHub service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var RunnerHub_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "runner.RunnerHub", + HandlerType: (*RunnerHubServer)(nil), + Methods: []grpc.MethodDesc{}, + Streams: []grpc.StreamDesc{ + { + StreamName: "Connect", + Handler: _RunnerHub_Connect_Handler, + ServerStreams: true, + ClientStreams: true, + }, + }, + Metadata: "proto/runner/runner.proto", +} diff --git a/proto/runner/runner.pb.go b/proto/runner/runner.pb.go index 53e154a..dff09e9 100644 --- a/proto/runner/runner.pb.go +++ b/proto/runner/runner.pb.go @@ -25,12 +25,13 @@ const ( type TaskType int32 const ( - TaskType_TASK_TYPE_UNKNOWN TaskType = 0 // 未知类型 - TaskType_TASK_TYPE_LOGIN TaskType = 1 // 登录验证 - TaskType_TASK_TYPE_GET_SCHEDULE TaskType = 2 // 获取课表 - TaskType_TASK_TYPE_GET_GRADES TaskType = 3 // 获取成绩 - TaskType_TASK_TYPE_GET_EXAMS TaskType = 4 // 获取考试安排 - TaskType_TASK_TYPE_GET_USER_INFO TaskType = 5 // 获取用户信息 + TaskType_TASK_TYPE_UNKNOWN TaskType = 0 // 未知类型 + TaskType_TASK_TYPE_LOGIN TaskType = 1 // 登录验证 + TaskType_TASK_TYPE_GET_SCHEDULE TaskType = 2 // 获取课表 + TaskType_TASK_TYPE_GET_GRADES TaskType = 3 // 获取成绩 + TaskType_TASK_TYPE_GET_EXAMS TaskType = 4 // 获取考试安排 + TaskType_TASK_TYPE_GET_USER_INFO TaskType = 5 // 获取用户信息 + TaskType_TASK_TYPE_GET_EMPTY_CLASSROOM TaskType = 6 // 获取空教室 ) // Enum value maps for TaskType. @@ -42,14 +43,16 @@ var ( 3: "TASK_TYPE_GET_GRADES", 4: "TASK_TYPE_GET_EXAMS", 5: "TASK_TYPE_GET_USER_INFO", + 6: "TASK_TYPE_GET_EMPTY_CLASSROOM", } TaskType_value = map[string]int32{ - "TASK_TYPE_UNKNOWN": 0, - "TASK_TYPE_LOGIN": 1, - "TASK_TYPE_GET_SCHEDULE": 2, - "TASK_TYPE_GET_GRADES": 3, - "TASK_TYPE_GET_EXAMS": 4, - "TASK_TYPE_GET_USER_INFO": 5, + "TASK_TYPE_UNKNOWN": 0, + "TASK_TYPE_LOGIN": 1, + "TASK_TYPE_GET_SCHEDULE": 2, + "TASK_TYPE_GET_GRADES": 3, + "TASK_TYPE_GET_EXAMS": 4, + "TASK_TYPE_GET_USER_INFO": 5, + "TASK_TYPE_GET_EMPTY_CLASSROOM": 6, } ) @@ -1711,6 +1714,237 @@ func (x *UserInfoResultData) GetGrade() string { return "" } +// GetEmptyClassroomPayload 获取空教室任务载荷 +type GetEmptyClassroomPayload struct { + state protoimpl.MessageState `protogen:"open.v1"` + Username string `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty"` // 学号 + Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"` // 密码 + Semester string `protobuf:"bytes,3,opt,name=semester,proto3" json:"semester,omitempty"` // 学期 + WeekStart string `protobuf:"bytes,4,opt,name=week_start,json=weekStart,proto3" json:"week_start,omitempty"` // 起始周次 + WeekEnd string `protobuf:"bytes,5,opt,name=week_end,json=weekEnd,proto3" json:"week_end,omitempty"` // 结束周次 + CampusCode string `protobuf:"bytes,6,opt,name=campus_code,json=campusCode,proto3" json:"campus_code,omitempty"` // 校区代码 + BuildingCode string `protobuf:"bytes,7,opt,name=building_code,json=buildingCode,proto3" json:"building_code,omitempty"` // 楼号代码(可选) + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetEmptyClassroomPayload) Reset() { + *x = GetEmptyClassroomPayload{} + mi := &file_proto_runner_runner_proto_msgTypes[21] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetEmptyClassroomPayload) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetEmptyClassroomPayload) ProtoMessage() {} + +func (x *GetEmptyClassroomPayload) ProtoReflect() protoreflect.Message { + mi := &file_proto_runner_runner_proto_msgTypes[21] + 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 GetEmptyClassroomPayload.ProtoReflect.Descriptor instead. +func (*GetEmptyClassroomPayload) Descriptor() ([]byte, []int) { + return file_proto_runner_runner_proto_rawDescGZIP(), []int{21} +} + +func (x *GetEmptyClassroomPayload) GetUsername() string { + if x != nil { + return x.Username + } + return "" +} + +func (x *GetEmptyClassroomPayload) GetPassword() string { + if x != nil { + return x.Password + } + return "" +} + +func (x *GetEmptyClassroomPayload) GetSemester() string { + if x != nil { + return x.Semester + } + return "" +} + +func (x *GetEmptyClassroomPayload) GetWeekStart() string { + if x != nil { + return x.WeekStart + } + return "" +} + +func (x *GetEmptyClassroomPayload) GetWeekEnd() string { + if x != nil { + return x.WeekEnd + } + return "" +} + +func (x *GetEmptyClassroomPayload) GetCampusCode() string { + if x != nil { + return x.CampusCode + } + return "" +} + +func (x *GetEmptyClassroomPayload) GetBuildingCode() string { + if x != nil { + return x.BuildingCode + } + return "" +} + +// EmptyClassroomResultData 空教室结果数据 +type EmptyClassroomResultData 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"` // 学号 + Classrooms []*EmptyClassroomEntry `protobuf:"bytes,3,rep,name=classrooms,proto3" json:"classrooms,omitempty"` // 空教室列表 + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *EmptyClassroomResultData) Reset() { + *x = EmptyClassroomResultData{} + mi := &file_proto_runner_runner_proto_msgTypes[22] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *EmptyClassroomResultData) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EmptyClassroomResultData) ProtoMessage() {} + +func (x *EmptyClassroomResultData) ProtoReflect() protoreflect.Message { + mi := &file_proto_runner_runner_proto_msgTypes[22] + 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 EmptyClassroomResultData.ProtoReflect.Descriptor instead. +func (*EmptyClassroomResultData) Descriptor() ([]byte, []int) { + return file_proto_runner_runner_proto_rawDescGZIP(), []int{22} +} + +func (x *EmptyClassroomResultData) GetSemester() string { + if x != nil { + return x.Semester + } + return "" +} + +func (x *EmptyClassroomResultData) GetStudentId() string { + if x != nil { + return x.StudentId + } + return "" +} + +func (x *EmptyClassroomResultData) GetClassrooms() []*EmptyClassroomEntry { + if x != nil { + return x.Classrooms + } + return nil +} + +// EmptyClassroomEntry 空教室条目 +type EmptyClassroomEntry struct { + state protoimpl.MessageState `protogen:"open.v1"` + Classroom string `protobuf:"bytes,1,opt,name=classroom,proto3" json:"classroom,omitempty"` // 教室名称 + Weekday string `protobuf:"bytes,2,opt,name=weekday,proto3" json:"weekday,omitempty"` // 星期几 + Periods string `protobuf:"bytes,3,opt,name=periods,proto3" json:"periods,omitempty"` // 可用节次 + Term string `protobuf:"bytes,4,opt,name=term,proto3" json:"term,omitempty"` // 学期描述 + Weeks string `protobuf:"bytes,5,opt,name=weeks,proto3" json:"weeks,omitempty"` // 周次范围 + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *EmptyClassroomEntry) Reset() { + *x = EmptyClassroomEntry{} + mi := &file_proto_runner_runner_proto_msgTypes[23] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *EmptyClassroomEntry) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EmptyClassroomEntry) ProtoMessage() {} + +func (x *EmptyClassroomEntry) ProtoReflect() protoreflect.Message { + mi := &file_proto_runner_runner_proto_msgTypes[23] + 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 EmptyClassroomEntry.ProtoReflect.Descriptor instead. +func (*EmptyClassroomEntry) Descriptor() ([]byte, []int) { + return file_proto_runner_runner_proto_rawDescGZIP(), []int{23} +} + +func (x *EmptyClassroomEntry) GetClassroom() string { + if x != nil { + return x.Classroom + } + return "" +} + +func (x *EmptyClassroomEntry) GetWeekday() string { + if x != nil { + return x.Weekday + } + return "" +} + +func (x *EmptyClassroomEntry) GetPeriods() string { + if x != nil { + return x.Periods + } + return "" +} + +func (x *EmptyClassroomEntry) GetTerm() string { + if x != nil { + return x.Term + } + return "" +} + +func (x *EmptyClassroomEntry) GetWeeks() string { + if x != nil { + return x.Weeks + } + return "" +} + var File_proto_runner_runner_proto protoreflect.FileDescriptor const file_proto_runner_runner_proto_rawDesc = "" + @@ -1849,14 +2083,38 @@ const file_proto_runner_runner_proto_rawDesc = "" + "\x05major\x18\x05 \x01(\tR\x05major\x12\x1d\n" + "\n" + "class_name\x18\x06 \x01(\tR\tclassName\x12\x14\n" + - "\x05grade\x18\a \x01(\tR\x05grade*\xa2\x01\n" + + "\x05grade\x18\a \x01(\tR\x05grade\"\xee\x01\n" + + "\x18GetEmptyClassroomPayload\x12\x1a\n" + + "\busername\x18\x01 \x01(\tR\busername\x12\x1a\n" + + "\bpassword\x18\x02 \x01(\tR\bpassword\x12\x1a\n" + + "\bsemester\x18\x03 \x01(\tR\bsemester\x12\x1d\n" + + "\n" + + "week_start\x18\x04 \x01(\tR\tweekStart\x12\x19\n" + + "\bweek_end\x18\x05 \x01(\tR\aweekEnd\x12\x1f\n" + + "\vcampus_code\x18\x06 \x01(\tR\n" + + "campusCode\x12#\n" + + "\rbuilding_code\x18\a \x01(\tR\fbuildingCode\"\x92\x01\n" + + "\x18EmptyClassroomResultData\x12\x1a\n" + + "\bsemester\x18\x01 \x01(\tR\bsemester\x12\x1d\n" + + "\n" + + "student_id\x18\x02 \x01(\tR\tstudentId\x12;\n" + + "\n" + + "classrooms\x18\x03 \x03(\v2\x1b.runner.EmptyClassroomEntryR\n" + + "classrooms\"\x91\x01\n" + + "\x13EmptyClassroomEntry\x12\x1c\n" + + "\tclassroom\x18\x01 \x01(\tR\tclassroom\x12\x18\n" + + "\aweekday\x18\x02 \x01(\tR\aweekday\x12\x18\n" + + "\aperiods\x18\x03 \x01(\tR\aperiods\x12\x12\n" + + "\x04term\x18\x04 \x01(\tR\x04term\x12\x14\n" + + "\x05weeks\x18\x05 \x01(\tR\x05weeks*\xc5\x01\n" + "\bTaskType\x12\x15\n" + "\x11TASK_TYPE_UNKNOWN\x10\x00\x12\x13\n" + "\x0fTASK_TYPE_LOGIN\x10\x01\x12\x1a\n" + "\x16TASK_TYPE_GET_SCHEDULE\x10\x02\x12\x18\n" + "\x14TASK_TYPE_GET_GRADES\x10\x03\x12\x17\n" + "\x13TASK_TYPE_GET_EXAMS\x10\x04\x12\x1b\n" + - "\x17TASK_TYPE_GET_USER_INFO\x10\x05*\x8a\x01\n" + + "\x17TASK_TYPE_GET_USER_INFO\x10\x05\x12!\n" + + "\x1dTASK_TYPE_GET_EMPTY_CLASSROOM\x10\x06*\x8a\x01\n" + "\n" + "TaskStatus\x12\x17\n" + "\x13TASK_STATUS_UNKNOWN\x10\x00\x12\x17\n" + @@ -1880,32 +2138,35 @@ 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, 22) +var file_proto_runner_runner_proto_msgTypes = make([]protoimpl.MessageInfo, 25) var file_proto_runner_runner_proto_goTypes = []any{ - (TaskType)(0), // 0: runner.TaskType - (TaskStatus)(0), // 1: runner.TaskStatus - (*StreamMessage)(nil), // 2: runner.StreamMessage - (*RegisterRequest)(nil), // 3: runner.RegisterRequest - (*RegisterResponse)(nil), // 4: runner.RegisterResponse - (*Heartbeat)(nil), // 5: runner.Heartbeat - (*HeartbeatAck)(nil), // 6: runner.HeartbeatAck - (*Task)(nil), // 7: runner.Task - (*TaskCancel)(nil), // 8: runner.TaskCancel - (*TaskResult)(nil), // 9: runner.TaskResult - (*LoginPayload)(nil), // 10: runner.LoginPayload - (*GetSchedulePayload)(nil), // 11: runner.GetSchedulePayload - (*GetGradesPayload)(nil), // 12: runner.GetGradesPayload - (*GetExamsPayload)(nil), // 13: runner.GetExamsPayload - (*ScheduleResultData)(nil), // 14: runner.ScheduleResultData - (*Course)(nil), // 15: runner.Course - (*ScheduleTime)(nil), // 16: runner.ScheduleTime - (*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 + (TaskType)(0), // 0: runner.TaskType + (TaskStatus)(0), // 1: runner.TaskStatus + (*StreamMessage)(nil), // 2: runner.StreamMessage + (*RegisterRequest)(nil), // 3: runner.RegisterRequest + (*RegisterResponse)(nil), // 4: runner.RegisterResponse + (*Heartbeat)(nil), // 5: runner.Heartbeat + (*HeartbeatAck)(nil), // 6: runner.HeartbeatAck + (*Task)(nil), // 7: runner.Task + (*TaskCancel)(nil), // 8: runner.TaskCancel + (*TaskResult)(nil), // 9: runner.TaskResult + (*LoginPayload)(nil), // 10: runner.LoginPayload + (*GetSchedulePayload)(nil), // 11: runner.GetSchedulePayload + (*GetGradesPayload)(nil), // 12: runner.GetGradesPayload + (*GetExamsPayload)(nil), // 13: runner.GetExamsPayload + (*ScheduleResultData)(nil), // 14: runner.ScheduleResultData + (*Course)(nil), // 15: runner.Course + (*ScheduleTime)(nil), // 16: runner.ScheduleTime + (*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 + (*GetEmptyClassroomPayload)(nil), // 23: runner.GetEmptyClassroomPayload + (*EmptyClassroomResultData)(nil), // 24: runner.EmptyClassroomResultData + (*EmptyClassroomEntry)(nil), // 25: runner.EmptyClassroomEntry + nil, // 26: runner.RegisterRequest.CapabilitiesEntry } var file_proto_runner_runner_proto_depIdxs = []int32{ 3, // 0: runner.StreamMessage.register:type_name -> runner.RegisterRequest @@ -1915,7 +2176,7 @@ 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 - 23, // 7: runner.RegisterRequest.capabilities:type_name -> runner.RegisterRequest.CapabilitiesEntry + 26, // 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 @@ -1923,13 +2184,14 @@ var file_proto_runner_runner_proto_depIdxs = []int32{ 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 + 25, // 15: runner.EmptyClassroomResultData.classrooms:type_name -> runner.EmptyClassroomEntry + 2, // 16: runner.RunnerHub.Connect:input_type -> runner.StreamMessage + 2, // 17: runner.RunnerHub.Connect:output_type -> runner.StreamMessage + 17, // [17:18] is the sub-list for method output_type + 16, // [16:17] is the sub-list for method input_type + 16, // [16:16] is the sub-list for extension type_name + 16, // [16:16] is the sub-list for extension extendee + 0, // [0:16] is the sub-list for field type_name } func init() { file_proto_runner_runner_proto_init() } @@ -1952,7 +2214,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: 22, + NumMessages: 25, NumExtensions: 0, NumServices: 1, }, diff --git a/proto/runner/runner.proto b/proto/runner/runner.proto index 415d6d7..7e51a55 100644 --- a/proto/runner/runner.proto +++ b/proto/runner/runner.proto @@ -81,6 +81,7 @@ enum TaskType { TASK_TYPE_GET_GRADES = 3; // 获取成绩 TASK_TYPE_GET_EXAMS = 4; // 获取考试安排 TASK_TYPE_GET_USER_INFO = 5; // 获取用户信息 + TASK_TYPE_GET_EMPTY_CLASSROOM = 6; // 获取空教室 } // TaskStatus 任务状态枚举 @@ -236,3 +237,30 @@ message UserInfoResultData { string class_name = 6; // 班级 string grade = 7; // 年级 } + +// GetEmptyClassroomPayload 获取空教室任务载荷 +message GetEmptyClassroomPayload { + string username = 1; // 学号 + string password = 2; // 密码 + string semester = 3; // 学期 + string week_start = 4; // 起始周次 + string week_end = 5; // 结束周次 + string campus_code = 6; // 校区代码 + string building_code = 7; // 楼号代码(可选) +} + +// EmptyClassroomResultData 空教室结果数据 +message EmptyClassroomResultData { + string semester = 1; // 学期 + string student_id = 2; // 学号 + repeated EmptyClassroomEntry classrooms = 3; // 空教室列表 +} + +// EmptyClassroomEntry 空教室条目 +message EmptyClassroomEntry { + string classroom = 1; // 教室名称 + string weekday = 2; // 星期几 + string periods = 3; // 可用节次 + string term = 4; // 学期描述 + string weeks = 5; // 周次范围 +}