diff --git a/README.md b/README.md index 947730a..a774d86 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,12 @@ go run . combine This looks for all files named `data/courses-{year}.json` and merges them. +You can also do the inverse, splitting a single `data/courses.json` into multiple `data/courses-{year}.json`. + +```bash +go run . split +``` + ### Running the server The server listens for web requests on port 7500. (It also spawns a Redis instance, using Docker, on port 7501.) diff --git a/main.go b/main.go index 17e2df8..b9d7964 100644 --- a/main.go +++ b/main.go @@ -7,6 +7,7 @@ import ( "log" "os" "path/filepath" + "sort" "classes.wtf/datasource" "classes.wtf/server" @@ -78,6 +79,46 @@ func main() { } log.Printf("wrote %d courses to data/courses.json", len(courses)) + case "split": + splitCmd := flag.NewFlagSet("split", flag.ExitOnError) + splitCmd.Parse(os.Args[2:]) + + filename := "data/courses.json" + + log.Printf("parsing combined course data from %s", filename) + file, err := os.Open(filename) + if err != nil { + log.Fatalf("failed to open %s: %v", filename, err) + } + var courses []datasource.Course + if err = json.NewDecoder(file).Decode(&courses); err != nil { + log.Fatalf("failed to parse %s: %v", filename, err) + } + + log.Printf("got %d courses; splitting by year", len(courses)) + coursesByYear := make(map[uint32][]datasource.Course) + for _, course := range courses { + coursesByYear[course.AcademicYear] = append(coursesByYear[course.AcademicYear], course) + } + years := make([]uint32, 0, len(coursesByYear)) + for year := range coursesByYear { + years = append(years, year) + } + sort.Slice(years, func(i, j int) bool { return years[i] < years[j] }) + + log.Printf("writing") + for _, year := range years { + filename := fmt.Sprintf("data/courses-%d.json", year) + yearCourses := coursesByYear[year] + log.Printf(" - %s [len: %d]", filename, len(yearCourses)) + yearCoursesJson, _ := json.Marshal(yearCourses) + if err := os.WriteFile(filename, yearCoursesJson, 0644); err != nil { + log.Fatalf("failed to write %s: %v", filename, err) + } + } + + log.Printf("wrote %d courses", len(courses)) + case "server": serverCmd := flag.NewFlagSet("server", flag.ExitOnError) data := serverCmd.String("data", "", "path or url for the data file")