courseSwap

package
v0.0.6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 15, 2026 License: MIT Imports: 16 Imported by: 0

README

换课程序核心逻辑总结

本模块 (./client/courseSwap) 实现了自动化的换课辅助功能,包含核心业务逻辑与用户交互界面。以下是其核心设计与逻辑总结:

1. 双模式支持 (CLI & GUI)

程序设计了灵活的入口,能够根据运行环境或参数切换交互模式,但底层逻辑复用同一套核心代码。

  • 命令行模式 (CLI): 基于 cobra 库实现 (client/main.go)。通过 client.exe cli 启动,提供交互式的问答流程(如输入文件路径、老师姓名等)。
  • 图形界面模式 (GUI): 基于 fyne 库实现 (client/run_windows.go)。这是 Windows 下的默认启动模式。UI 包含文件选择器、日期选择器、下拉菜单以及左右分栏的布局(左侧操作,右侧日志与结果列表)。
  • 核心复用: 无论是 CLI 还是 GUI,最终都调用 client/courseSwap 包下的 CalculateSwapCandidatesExecuteSwap 等函数执行业务逻辑。

2. 课程表源文件解析

  • 解析器: client/courseSwap/parser.go 使用 excelize 库读取 Excel 文件。
  • 识别逻辑: 程序并不假设固定的行号,而是遍历 Sheet 寻找关键字 "节次" 来定位每个老师的课表区域。
  • 数据结构: 解析结果被映射为 teacherInfoMap,包含老师姓名及其对应的静态课程列表(周几、第几节、班级、教室)。
  • 冲突检测: 解析过程中会校验同一老师在同一时间段是否有多门课程,防止源数据错误。

3. 从“静态课表”到“动态日程”的推演

这是非开发人员容易误解的核心难点。Excel 里的课表是静态的、周期性的(如“每周一第一节”),但换课是针对具体日期的(如“2024年1月1日的第一节”)。

  • 时间投影: client/courseSwap/courseSwap.go 中的逻辑会将静态的“周一至周五”映射到具体的日历日期上。
  • 未来推演: 程序会计算当前日期是周几,然后向后推演未来几周(代码中设定为 3 周或 21 天)的具体课程安排。
  • 意义: 只有将课程实例化为带日期的对象 (CourseInfo 包含 Date 字段),才能实现“只换这一天的课,而不影响下周同一时间的课”。

4. 换课记录的存储与“回放”计算

换课不是修改 Excel 源文件,而是通过“叠加记录”的方式动态计算出来的。

  • 存储层: 支持本地 SQLite (storageLocal.go) 和云端 API (storageCloud.go) 两种存储方式,通过 CourseSwapRepo 接口统一调用。
  • 计算逻辑: 在计算候选课程时 (CalculateSwapCandidates),程序会先加载内存中的基础课表,然后读取并回放所有的换课历史记录。
  • 状态叠加: 如果存在一条“A老师和B老师在X日期互换”的记录,程序会在内存中交换这两节课的属性。因此,用户看到的最终列表是应用了所有历史换课记录后的最新状态。
  • 删除回滚: 删除功能 (DeleteSwapHistory) 本质上是移除了这条记录,下次计算时不再应用该交换,从而实现逻辑上的“回滚”。

5. 参数缓存机制

为了提升用户体验,避免重复输入繁琐的路径和名字。

  • 实现: client/courseSwap/input.go 定义了 InputConfig 结构体和 SaveCache/LoadCache 方法。
  • 持久化: 参数被序列化为 JSON 文件 (course_swap_cache.json) 保存在本地。
  • 应用:
    • CLI: 在提示用户输入时,会显示缓存的值作为默认选项(直接回车即可使用)。
    • GUI: 启动时自动填充输入框、文件路径选择器和下拉菜单的选中项。

Documentation

Index

Constants

View Source
const (
	WeekTypeAll = iota
	WeekTypeOdd
	WeekTypeEven
)

--------------------------------------------------

View Source
const (
	CourseNumMax = 8
)

Variables

This section is empty.

Functions

func CalculateSwapCandidates added in v0.0.6

func CalculateSwapCandidates(config InputConfig) (*courseManager, error)

计算换课候选列表

func CourseSwapCli added in v0.0.6

func CourseSwapCli()

func DeleteSwapHistory added in v0.0.6

func DeleteSwapHistory(storageType string, id int32) error

删除换课记录

func ExecuteSwap added in v0.0.6

func ExecuteSwap(config InputConfig, target *CourseInfo) error

保存换课记录

func GetSwapHistory added in v0.0.6

func GetSwapHistory(storageType string) ([]swagger.ApiCourseSwapRequestInfo, error)

获取换课历史记录

func GetTeacherList added in v0.0.6

func GetTeacherList(path string) ([]string, error)

下拉:教师列表

func NewCourseParser

func NewCourseParser(path string) *courseParser

func SaveCache added in v0.0.6

func SaveCache(cache InputConfig)

Types

type CloudRepo added in v0.0.6

type CloudRepo struct {
	// contains filtered or unexported fields
}

func NewCloudRepo added in v0.0.6

func NewCloudRepo() *CloudRepo

func (*CloudRepo) AddCourseSwapRequest added in v0.0.6

func (r *CloudRepo) AddCourseSwapRequest(ctx context.Context, req *swagger.ApiCourseSwapRequestInfo) error

func (*CloudRepo) DeleteCourseSwapRequest added in v0.0.6

func (r *CloudRepo) DeleteCourseSwapRequest(ctx context.Context, id int32) error

func (*CloudRepo) GetCourseSwapRequestList added in v0.0.6

func (r *CloudRepo) GetCourseSwapRequestList(ctx context.Context) ([]swagger.ApiCourseSwapRequestInfo, error)

type CourseInfo added in v0.0.6

type CourseInfo struct {
	ClassName     string //课名
	ClassRoomName string //班级名
	ClassNum      int
	Date          time.Time
	Teacher       string
	WeekType      int // 0:All, 1:Odd, 2:Even
}

实在词穷,courseInfo表示课程安排,如20240101一年1班的第1节课 而classInfo表示课程表中的一节课,如周三一年1班的第1节课

func (*CourseInfo) String added in v0.0.6

func (c *CourseInfo) String() string

type CourseSwapRepo added in v0.0.6

type CourseSwapRepo interface {
	GetCourseSwapRequestList(ctx context.Context) ([]swagger.ApiCourseSwapRequestInfo, error)
	AddCourseSwapRequest(ctx context.Context, req *swagger.ApiCourseSwapRequestInfo) error
	DeleteCourseSwapRequest(ctx context.Context, id int32) error
}

type CourseSwapRequestModel added in v0.0.6

type CourseSwapRequestModel struct {
	ID           int32 `gorm:"primaryKey;autoIncrement"`
	SrcTeacher   string
	SrcDate      string
	SrcCourseNum int32
	SrcCourse    string
	SrcClass     string
	DstTeacher   string
	DstDate      string
	DstCourseNum int32
	DstCourse    string
	DstClass     string
	CreateTime   string
	Status       int32
}

func (CourseSwapRequestModel) TableName added in v0.0.6

func (CourseSwapRequestModel) TableName() string

type InputConfig added in v0.0.6

type InputConfig struct {
	Path        string `json:"path"`
	Teacher     string `json:"teacher"`
	Date        string `json:"date"`
	CourseNum   int    `json:"courseNum"`
	StorageType string `json:"storageType"`
	IsOddWeek   bool   `json:"isOddWeek"`
}

func InputParams added in v0.0.6

func InputParams() (config InputConfig, err error)

func LoadCache added in v0.0.6

func LoadCache() InputConfig

type LocalRepo added in v0.0.6

type LocalRepo struct {
	// contains filtered or unexported fields
}

func NewLocalRepo added in v0.0.6

func NewLocalRepo() *LocalRepo

func (*LocalRepo) AddCourseSwapRequest added in v0.0.6

func (r *LocalRepo) AddCourseSwapRequest(ctx context.Context, req *swagger.ApiCourseSwapRequestInfo) error

func (*LocalRepo) DeleteCourseSwapRequest added in v0.0.6

func (r *LocalRepo) DeleteCourseSwapRequest(ctx context.Context, id int32) error

func (*LocalRepo) GetCourseSwapRequestList added in v0.0.6

func (r *LocalRepo) GetCourseSwapRequestList(ctx context.Context) ([]swagger.ApiCourseSwapRequestInfo, error)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL