package main import ( "encoding/csv" "encoding/json" "fmt" "log" "math/rand" "os" "strings" "time" "github.com/brianvoe/gofakeit/v6" ) var course_type = []string{ "A", "B", "C", "D", "E", } var course_information = []Section{ {CourseNumber: "B560", CourseTitle: "Academic Legal Writing: Dissertation Fundamentals"}, {CourseNumber: "B652", CourseTitle: "Accounting for Lawyers"}, {CourseNumber: "B713", CourseTitle: "Administrative Law"}, {CourseNumber: "B528", CourseTitle: "Advanced Appellate Advocacy"}, {CourseNumber: "B631", CourseTitle: "Advanced Bankruptcy: Business Reorganization"}, {CourseNumber: "B634", CourseTitle: "Advanced Constitutional Law: Issues Related to the Press"}, {CourseNumber: "B634", CourseTitle: "Advanced Constitutional Law"}, {CourseNumber: "B595", CourseTitle: "Advanced Environmental Law and Practice"}, {CourseNumber: "B639", CourseTitle: "Advanced Legal Research"}, {CourseNumber: "B639", CourseTitle: "Advanced Legal Research: LLMs and SJDs"}, {CourseNumber: "B791", CourseTitle: "Advanced Legal Writing"}, {CourseNumber: "B517", CourseTitle: "Advanced Patent Law"}, {CourseNumber: "B720", CourseTitle: "Advanced Trial Practice"}, {CourseNumber: "B734", CourseTitle: "Advocacy: ABA"}, {CourseNumber: "B734", CourseTitle: "Advocacy: AIPLA"}, {CourseNumber: "B734", CourseTitle: "Advocacy: External Moot Court Team"}, {CourseNumber: "B734", CourseTitle: "Advocacy: IP"}, {CourseNumber: "B734", CourseTitle: "Advocacy: International Patent Drafting"}, {CourseNumber: "B734", CourseTitle: "Advocacy: LawMeet"}, {CourseNumber: "B734", CourseTitle: "Advocacy: Moot Court Board"}, {CourseNumber: "B734", CourseTitle: "Advocacy: Pace Moot Court Team"}, {CourseNumber: "B540", CourseTitle: "After Atrocities: Processes of Post-Conflict Justice"}, {CourseNumber: "B570", CourseTitle: "American Constitutional Law for Foreign Lawyers"}, {CourseNumber: "B659", CourseTitle: "American Legal History"}, {CourseNumber: "B729", CourseTitle: "Antitrust Law"}, {CourseNumber: "B642", CourseTitle: "Appellate Advocacy"}, {CourseNumber: "B671", CourseTitle: "Appellate Practice and Procedure"}, {CourseNumber: "B671", CourseTitle: "Appellate Practice and Procedure: Criminal Appeal: From Transcript to Argument"}, {CourseNumber: "B710", CourseTitle: "Cybersecurity Clinic"}, {CourseNumber: "B769", CourseTitle: "Banking Law"}, {CourseNumber: "B725", CourseTitle: "Bankruptcy"}, {CourseNumber: "B793", CourseTitle: "Business and Human Rights"}, {CourseNumber: "B632", CourseTitle: "Business Planning"}, {CourseNumber: "B614", CourseTitle: "Career Choices"}, {CourseNumber: "B674", CourseTitle: "Center for Constitutional Democracy"}, {CourseNumber: "B781", CourseTitle: "Children and the Law"}, {CourseNumber: "B533", CourseTitle: "Civil Procedure"}, {CourseNumber: "B534", CourseTitle: "Civil Procedure II"}, {CourseNumber: "B580", CourseTitle: "Civil Rights Statutes"}, {CourseNumber: "B506", CourseTitle: "Climate Law and Policy"}, {CourseNumber: "B688", CourseTitle: "Community Legal Clinic"}, {CourseNumber: "B748", CourseTitle: "Comparative Law: Comparative Legal Systems"}, {CourseNumber: "B748", CourseTitle: "Comparative Law: Constitutional Design and the Economy"}, {CourseNumber: "B748", CourseTitle: "Comparative Law: Islam and Human Rights"}, {CourseNumber: "B667", CourseTitle: "Complex Litigation"}, {CourseNumber: "B745", CourseTitle: "Conflict of Laws"}, {CourseNumber: "B558", CourseTitle: "Conservation Law Clinic"}, {CourseNumber: "B575", CourseTitle: "Constitutional Design in Multiethnic Societies"}, {CourseNumber: "B760", CourseTitle: "Constitutional History Colloquium"}, {CourseNumber: "B513", CourseTitle: "Constitutional Law"}, {CourseNumber: "B668", CourseTitle: "Constitutional Law II"}, {CourseNumber: "B606", CourseTitle: "Constitutional Litigation"}, {CourseNumber: "B501", CourseTitle: "Contracts"}, {CourseNumber: "B662", CourseTitle: "Copyright Law"}, {CourseNumber: "B656", CourseTitle: "Corporate Finance Law"}, {CourseNumber: "B700", CourseTitle: "Corporate Taxation"}, {CourseNumber: "B653", CourseTitle: "Corporations"}, {CourseNumber: "B511", CourseTitle: "Criminal Law"}, {CourseNumber: "B545", CourseTitle: "Criminal Law Externship"}, {CourseNumber: "B786", CourseTitle: "Criminal Procedure Capstone"}, {CourseNumber: "B604", CourseTitle: "Criminal Procedure: LLM"}, {CourseNumber: "B602", CourseTitle: "Criminal Procedure: Trial"}, {CourseNumber: "B601", CourseTitle: "Criminal Process: Investigation"}, {CourseNumber: "B587", CourseTitle: "Cybersecurity Law I"}, {CourseNumber: "B738", CourseTitle: "Cybersecurity Law II"}, {CourseNumber: "B710", CourseTitle: "Cybersecurity Law Clinic"}, {CourseNumber: "B581", CourseTitle: "Decision Making for Lawyers: Concepts, Duties and Skills"}, {CourseNumber: "B714", CourseTitle: "Deliberative Leadership"}, {CourseNumber: "B563", CourseTitle: "Domestic Relations Mediation"}, {CourseNumber: "B680", CourseTitle: "Employment Discrimination"}, {CourseNumber: "B719", CourseTitle: "Employment Law"}, {CourseNumber: "B590", CourseTitle: "Entertainment Law"}, {CourseNumber: "B561", CourseTitle: "Entrepreneurship Law Clinic"}, {CourseNumber: "B740", CourseTitle: "Estate Planning"}, {CourseNumber: "B611", CourseTitle: "Ethics and Compliance"}, {CourseNumber: "B755", CourseTitle: "European Union Law"}, {CourseNumber: "B723", CourseTitle: "Evidence"}, {CourseNumber: "B691", CourseTitle: "Family and Children Mediation Clinic"}, {CourseNumber: "B608", CourseTitle: "Family Law"}, {CourseNumber: "B532", CourseTitle: "Federal Circuit Advocacy"}, {CourseNumber: "B739", CourseTitle: "Federal Criminal Law and White Collar Crime"}, {CourseNumber: "B571", CourseTitle: "Federal Habeas Litigation"}, {CourseNumber: "B733", CourseTitle: "Federal Jurisdiction"}, {CourseNumber: "B789", CourseTitle: "Feminist Jurisprudence"}, {CourseNumber: "B568", CourseTitle: "Gender and The Law"}, {CourseNumber: "B536", CourseTitle: "Health Law"}, {CourseNumber: "B536", CourseTitle: "Health Privacy Law"}, {CourseNumber: "B793", CourseTitle: "Human Rights"}, {CourseNumber: "B669", CourseTitle: "Immigration Law"}, {CourseNumber: "B655", CourseTitle: "Information Privacy and Security Management Practicum"}, {CourseNumber: "B708", CourseTitle: "Information Privacy Law I"}, {CourseNumber: "B728", CourseTitle: "Information Privacy Law II"}, {CourseNumber: "B587", CourseTitle: "Information Security Law"}, {CourseNumber: "B710", CourseTitle: "Independent Clinical Project"}, {CourseNumber: "B572", CourseTitle: "Intellectual Property Clinic"}, {CourseNumber: "B551", CourseTitle: "Intellectual Property Externship"}, {CourseNumber: "B544", CourseTitle: "Intellectual Property Transactions"}, {CourseNumber: "B726", CourseTitle: "Intellectual Property/Antitrust"}, {CourseNumber: "B620", CourseTitle: "International Business Negotiations"}, {CourseNumber: "B735", CourseTitle: "International Business Transactions"}, {CourseNumber: "B565", CourseTitle: "International Criminal Law"}, {CourseNumber: "B783", CourseTitle: "International Environmental Law"}, {CourseNumber: "B549", CourseTitle: "International Intellectual Property"}, {CourseNumber: "B665", CourseTitle: "International Law"}, {CourseNumber: "B666", CourseTitle: "International Securities Regulation"}, {CourseNumber: "B759", CourseTitle: "International Trade"}, {CourseNumber: "B792", CourseTitle: "Internet Law"}, {CourseNumber: "B792", CourseTitle: "Internet Law: Political and Legal Dimensions"}, {CourseNumber: "B638", CourseTitle: "Introduction to American Legal Research"}, {CourseNumber: "B782", CourseTitle: "Introduction to Environmental Law"}, {CourseNumber: "B650", CourseTitle: "Introduction to Income Tax"}, {CourseNumber: "B504", CourseTitle: "Introduction to Law"}, {CourseNumber: "B567", CourseTitle: "IP Practicum: Legal Aspects of Music"}, {CourseNumber: "B698", CourseTitle: "Judicial Field Placements"}, {CourseNumber: "B788", CourseTitle: "Labor and Employment Arbitration"}, {CourseNumber: "B663", CourseTitle: "Labor Law I"}, {CourseNumber: "B615", CourseTitle: "Land Use Controls"}, {CourseNumber: "B661", CourseTitle: "Law and Biomedical Advance"}, {CourseNumber: "B658", CourseTitle: "Law and Education: Advanced School Law"}, {CourseNumber: "B658", CourseTitle: "Law and Education: Higher Education"}, {CourseNumber: "B658", CourseTitle: "Law and Education: Leadership in Special Education"}, {CourseNumber: "B658", CourseTitle: "Law and Education: Legal Perspectives on Education"}, {CourseNumber: "B658", CourseTitle: "Law and Education: Workshop on Probs in Ed Leadership"}, {CourseNumber: "B761", CourseTitle: "Law and Philanthropy"}, {CourseNumber: "B592", CourseTitle: "Law and Political Theory: Institutional Analysis & Development"}, {CourseNumber: "B730", CourseTitle: "Law and Religion"}, {CourseNumber: "B744", CourseTitle: "Law and Social Psychology"}, {CourseNumber: "B678", CourseTitle: "Law and Sports"}, {CourseNumber: "B674", CourseTitle: "Law Journal: Indiana Journal of Global Legal Studies"}, {CourseNumber: "B674", CourseTitle: "Law Journal: Indiana Law Journal"}, {CourseNumber: "B674", CourseTitle: "Law Journal: Indiana Journal of Law and Social Equality"}, {CourseNumber: "B685", CourseTitle: "The Lawyer as a Business Executive"}, {CourseNumber: "B539", CourseTitle: "Lawyering in the Public Interest"}, {CourseNumber: "B530", CourseTitle: "Legal Discourse and Legal Writing for LLM and MCL Students"}, {CourseNumber: "B582", CourseTitle: "Legal Issues in Mergers and Acquisitions"}, {CourseNumber: "B508", CourseTitle: "Legal Operations"}, {CourseNumber: "B614", CourseTitle: "The Legal Profession (for 1Ls)"}, {CourseNumber: "B614", CourseTitle: "Legal Profession for Foreign Lawyers"}, {CourseNumber: "B542", CourseTitle: "Legal Research and Writing I"}, {CourseNumber: "B543", CourseTitle: "Legal Research and Writing II"}, {CourseNumber: "B554", CourseTitle: "Legislation"}, {CourseNumber: "B564", CourseTitle: "Litigation Drafting"}, {CourseNumber: "B771", CourseTitle: "Mediation"}, {CourseNumber: "B771", CourseTitle: "Mediation for LLMs"}, {CourseNumber: "B582", CourseTitle: "Mergers and Acquisitions"}, {CourseNumber: "B508", CourseTitle: "Modern Small Firm Practice"}, {CourseNumber: "B623", CourseTitle: "Negotiable Instruments"}, {CourseNumber: "B620", CourseTitle: "Negotiations"}, {CourseNumber: "B537", CourseTitle: "Nonprofit Law Clinic"}, {CourseNumber: "B569", CourseTitle: "Nonprofit Organizations"}, {CourseNumber: "B681", CourseTitle: "Partnership Tax"}, {CourseNumber: "B743", CourseTitle: "Patent Law"}, {CourseNumber: "B559", CourseTitle: "Patent Prosecution"}, {CourseNumber: "B785", CourseTitle: "Patent Trial Practice"}, {CourseNumber: "B643", CourseTitle: "Poverty Law"}, {CourseNumber: "B564", CourseTitle: "Pre-trial Litigation"}, {CourseNumber: "B564", CourseTitle: "Pre-trial Litigation: Courtroom Procedure"}, {CourseNumber: "B564", CourseTitle: "Pre-trial Litigation: Criminal Practice"}, {CourseNumber: "B564", CourseTitle: "Pre-trial Litigation: Depositions"}, {CourseNumber: "B622", CourseTitle: "Principles of Law and Economics"}, {CourseNumber: "B514", CourseTitle: "Private Practice Externship"}, {CourseNumber: "B654", CourseTitle: "Products Liability"}, {CourseNumber: "B515", CourseTitle: "Project Management"}, {CourseNumber: "B521", CourseTitle: "Property"}, {CourseNumber: "B564", CourseTitle: "Protection Order Litigation"}, {CourseNumber: "B547", CourseTitle: "Public Interest Internship Program"}, {CourseNumber: "B675", CourseTitle: "Public Natural Resources"}, {CourseNumber: "B507", CourseTitle: "Public Speaking"}, {CourseNumber: "B756", CourseTitle: "Race, American Society and the Law"}, {CourseNumber: "B749", CourseTitle: "Real Estate Finance"}, {CourseNumber: "B775", CourseTitle: "Real Estate Transactions"}, {CourseNumber: "B603", CourseTitle: "Remedies and Equity"}, {CourseNumber: "B524", CourseTitle: "Representing the State"}, {CourseNumber: "B670", CourseTitle: "Sales"}, {CourseNumber: "B672", CourseTitle: "Secured Transactions"}, {CourseNumber: "B727", CourseTitle: "Securities Regulation"}, {CourseNumber: "B538", CourseTitle: "Semester Public Interest Program"}, {CourseNumber: "B649", CourseTitle: "State and Local Tax"}, {CourseNumber: "B519", CourseTitle: "State Constitutional Law"}, {CourseNumber: "B588", CourseTitle: "Strategies in Critical Reading and Writing: Family Law"}, {CourseNumber: "B751", CourseTitle: "Survey of Intellectual Property"}, {CourseNumber: "B526", CourseTitle: "Tax Policy Colloquium"}, {CourseNumber: "B736", CourseTitle: "Topics in Tax: Strategic Business and Tax Planning"}, {CourseNumber: "B531", CourseTitle: "Torts"}, {CourseNumber: "B758", CourseTitle: "Trademark and Unfair Competition"}, {CourseNumber: "B709", CourseTitle: "Transactional Drafting"}, {CourseNumber: "B709", CourseTitle: "Transactional Drafting: Anatomy of a Deal"}, {CourseNumber: "B709", CourseTitle: "Transactional Drafting: Real Estate"}, {CourseNumber: "B709", CourseTitle: "Transactional Drafting: Tax"}, {CourseNumber: "B722", CourseTitle: "Trial Advocacy"}, {CourseNumber: "B768", CourseTitle: "Water Law"}, {CourseNumber: "B550", CourseTitle: "Wildlife Law"}, {CourseNumber: "B645", CourseTitle: "Wills & Trusts"}, {CourseNumber: "L641", CourseTitle: "Constitutionalism in the Middle East"}, {CourseNumber: "L710", CourseTitle: "Seminar in Law and Society: Immigration Law"}, {CourseNumber: "L710", CourseTitle: "Seminar in Law and Society: Work, Family, and the Law"}, {CourseNumber: "L710", CourseTitle: "Seminar in Law and Society: Law and Language"}, {CourseNumber: "L782", CourseTitle: "Seminar in Administrative Law: Lawyering in the Modern Administrative State"}, {CourseNumber: "L766", CourseTitle: "Seminar in Children and the Law: Reproduction and Childhood"}, {CourseNumber: "L766", CourseTitle: "Seminar in Children and the Law"}, {CourseNumber: "L703", CourseTitle: "Seminar in Commercial Law: Consumer Credit"}, {CourseNumber: "L770", CourseTitle: "Seminar in Comparative Inequality"}, {CourseNumber: "L770", CourseTitle: "Seminar in Comparative Law: Islamic Law"}, {CourseNumber: "L736", CourseTitle: "Seminar in Congress, the Presidency and the Courts"}, {CourseNumber: "L799", CourseTitle: "Seminar in Constitutional Law: The Courts, the Democratic Process, and the People"}, {CourseNumber: "L684", CourseTitle: "Seminar in Constitutional Design: Rights, Gender, and States of Emergency"}, {CourseNumber: "L799", CourseTitle: "Seminar in Constitutional Law"}, {CourseNumber: "L799", CourseTitle: "Seminar in Constitutional Law: First Amendment"}, {CourseNumber: "L799", CourseTitle: "Seminar in Constitutional Law: Second Amendment"}, {CourseNumber: "L799", CourseTitle: "Seminar in Constitutional Law: Sexuality, Reproduction, and the Constitution"}, {CourseNumber: "L690", CourseTitle: "Seminar in Corporate Law: Financial Regulation"}, {CourseNumber: "L690", CourseTitle: "Seminar in Corporate Law: Law and Practice Intellegence Age"}, {CourseNumber: "L776", CourseTitle: "Seminar in Criminal Law: Current Issues in Law and Procedure"}, {CourseNumber: "L776", CourseTitle: "Seminar in Criminal Law: Federal Sentencing"}, {CourseNumber: "L776", CourseTitle: "Seminar in Criminal Law: Punishment in Theory and Practice"}, {CourseNumber: "L728", CourseTitle: "Seminar in Globalization"}, {CourseNumber: "L664", CourseTitle: "Seminar in Information Privacy"}, {CourseNumber: "L712", CourseTitle: "Seminar in International Law: Drone Law"}, {CourseNumber: "L730", CourseTitle: "Seminar in Intellectual Property"}, {CourseNumber: "L730", CourseTitle: "Seminar in Intellectual Property: Data Law and Policy"}, {CourseNumber: "L637", CourseTitle: "Seminar in Introduction to Biotechnological Innovation"}, {CourseNumber: "L797", CourseTitle: "Seminar in Jurisprudence"}, {CourseNumber: "L750", CourseTitle: "Seminar in Law and Development"}, {CourseNumber: "L713", CourseTitle: "Seminar in Law and Economics"}, {CourseNumber: "L796", CourseTitle: "Seminar in Law and Medicine"}, {CourseNumber: "L748", CourseTitle: "Seminar in Law and Psychology of Crime, Culpability, and Punishment"}, {CourseNumber: "L724", CourseTitle: "Seminar in Law and Society of China"}, {CourseNumber: "L773", CourseTitle: "Seminar in Tax Policy"}, {CourseNumber: "L636", CourseTitle: "Seminar in Transnational Law"}, {CourseNumber: "L639", CourseTitle: "Seminar in the Supreme Court as an Institution"}, {CourseNumber: "L714", CourseTitle: "Seminar on Judicial Conduct"}, } type User struct { UID string `json:"uid"` FirstName string `json:"first_name"` LastName string `json:"last_name"` Status string `json:"status"` ExamID string `json:"exam_id"` Username string `json:"username"` APIKey string `json:"api_key"` PasswordHash string `json:"password_hash"` } type Section struct { SectionID string `json:"section_id"` CourseNumber string `json:"course_number"` Instructor string `json:"course_instructor"` CourseTitle string `json:"course_title"` CourseType string `json:"course_type"` GradesDue string `json:"grades_due"` } type Config struct { NumberOfUsers int `json:"number_of_users"` NumberOfSections int `json:"number_of_sections"` EnrollmentsPerStudent int `json:"enrollments_per_student"` PercentStatus map[string]int `json:"percent_status"` } type InstructorsSections struct { InstructorID string `json:"uid"` SectionID string `json:"section_id"` } var statuses = []string{"JD", "LLM", "MCL", "PHD", "SJD", "MLS", "SPEC", "EXCH", "MNR", "CERT", "Admin", "Instructor"} func GenerateUserData(config Config) []User { // Build a weighted list of statuses weightedStatuses := make([]string, 0, 100) for status, pct := range config.PercentStatus { for i := 0; i < pct; i++ { weightedStatuses = append(weightedStatuses, status) } } // Generate unique ExamIDs and UIDs examIDs := uniqueNumericStrings(4, config.NumberOfUsers) uids := uniqueNumericStrings(10, config.NumberOfUsers) users := make([]User, config.NumberOfUsers) for i := range users { users[i] = User{ UID: uids[i], FirstName: gofakeit.FirstName(), LastName: gofakeit.LastName(), Status: weightedStatuses[rand.Intn(len(weightedStatuses))], ExamID: examIDs[i], Username: gofakeit.Username(), APIKey: strings.ReplaceAll(gofakeit.UUID(), "-", ""), PasswordHash: gofakeit.Password(true, true, true, true, false, 16), } } return users } func SaveGeneratedUsers(users []User) { f, err := os.Create("users.csv") if err != nil { log.Fatalf("failed to create users.csv: %v", err) } defer f.Close() w := csv.NewWriter(f) if err := w.Write([]string{"uid", "first_name", "last_name", "status", "exam_id", "username", "api_key", "password_hash"}); err != nil { log.Fatalf("failed to write csv header: %v", err) } for _, u := range users { if err := w.Write([]string{u.UID, u.FirstName, u.LastName, u.Status, u.ExamID, u.Username, u.APIKey, u.PasswordHash}); err != nil { log.Fatalf("failed to write csv row: %v", err) } } w.Flush() if err := w.Error(); err != nil { log.Fatalf("csv flush error: %v", err) } fmt.Printf("Generated %d users to users.csv\n", len(users)) } func GenerateSectionData(config Config, users []User) []Section { // Build list of instructor UIDs from users with Status "Instructor" instructorUIDs := make([]string, 0) for _, u := range users { if u.Status == "Instructor" { instructorUIDs = append(instructorUIDs, u.UID) } } if len(instructorUIDs) == 0 { log.Fatal("no users with Status \"Instructor\" found") } // Generate unique course numbers: one uppercase letter + 3 digits seenCourseNumbers := make(map[string]struct{}, config.NumberOfSections) courseNumbers := make([]string, 0, config.NumberOfSections) for len(courseNumbers) < config.NumberOfSections { cn := fmt.Sprintf("%c%03d", 'A'+rune(rand.Intn(26)), rand.Intn(1000)) if _, exists := seenCourseNumbers[cn]; !exists { seenCourseNumbers[cn] = struct{}{} courseNumbers = append(courseNumbers, cn) } } sectionIDs := uniqueNumericStrings(5, config.NumberOfSections) now := time.Now() dueDates := []string{ now.AddDate(0, 0, 7).Format("Monday 2 January 2006"), now.AddDate(0, 1, 0).Format("Monday 2 January 2006"), } sections := make([]Section, config.NumberOfSections) for i := range sections { my_section := course_information[rand.Intn(len(course_information))] my_section.SectionID = sectionIDs[i] my_section.Instructor = instructorUIDs[rand.Intn(len(instructorUIDs))] my_section.CourseType = "default" my_section.GradesDue = dueDates[rand.Intn(len(dueDates))] sections[i] = my_section } return sections } func SaveGeneratedSections(sections []Section) { f, err := os.Create("sections.csv") if err != nil { log.Fatalf("failed to create sections.csv: %v", err) } defer f.Close() w := csv.NewWriter(f) if err := w.Write([]string{"section_id", "course_number", "course_instructor", "course_title", "course_type", "grades_due"}); err != nil { log.Fatalf("failed to write csv header: %v", err) } for _, s := range sections { if err := w.Write([]string{s.SectionID, s.CourseNumber, s.Instructor, s.CourseTitle, s.CourseType, s.GradesDue}); err != nil { log.Fatalf("failed to write csv row: %v", err) } } w.Flush() if err := w.Error(); err != nil { log.Fatalf("csv flush error: %v", err) } fmt.Printf("Generated %d sections to sections.csv\n", len(sections)) } func GenerateInstructorAssignmentData(users []User, sections []Section) []InstructorsSections { instructorUIDs := make([]string, 0) for _, u := range users { if u.Status == "Instructor" { instructorUIDs = append(instructorUIDs, u.UID) } } if len(instructorUIDs) == 0 { log.Fatal("no users with Status \"Instructor\" found") } assignments := make([]InstructorsSections, len(sections)) for i, s := range sections { assignments[i] = InstructorsSections{ InstructorID: instructorUIDs[i%len(instructorUIDs)], SectionID: s.SectionID, } } return assignments } func SaveInstructorsSections(assignments []InstructorsSections) { f, err := os.Create("instructors_sections.csv") if err != nil { log.Fatalf("failed to create instructors_sections.csv: %v", err) } defer f.Close() w := csv.NewWriter(f) if err := w.Write([]string{"uid", "section_id"}); err != nil { log.Fatalf("failed to write csv header: %v", err) } for _, a := range assignments { if err := w.Write([]string{a.InstructorID, a.SectionID}); err != nil { log.Fatalf("failed to write csv row: %v", err) } } w.Flush() if err := w.Error(); err != nil { log.Fatalf("csv flush error: %v", err) } fmt.Printf("Generated %d instructor assignments to instructors_sections.csv\n", len(assignments)) } type SectionEnrollment struct { SectionID string `json:"section_id"` UID string `json:"uid"` } func GenerateSectionEnrollmentData(users []User, sections []Section, config Config) []SectionEnrollment { if config.EnrollmentsPerStudent > len(sections) { log.Fatalf("enrollments_per_student (%d) exceeds number of sections (%d)", config.EnrollmentsPerStudent, len(sections)) } enrollments := make([]SectionEnrollment, 0, len(users)*config.EnrollmentsPerStudent) for _, u := range users { // Shuffle a copy of section indices and take the first EnrollmentsPerStudent indices := rand.Perm(len(sections)) for _, idx := range indices[:config.EnrollmentsPerStudent] { enrollments = append(enrollments, SectionEnrollment{ SectionID: sections[idx].SectionID, UID: u.UID, }) } } return enrollments } func SaveGeneratedSectionEnrollments(enrollments []SectionEnrollment) { f, err := os.Create("section_enrollments.csv") if err != nil { log.Fatalf("failed to create section_enrollments.csv: %v", err) } defer f.Close() w := csv.NewWriter(f) if err := w.Write([]string{"section_id", "uid"}); err != nil { log.Fatalf("failed to write csv header: %v", err) } for _, e := range enrollments { if err := w.Write([]string{e.SectionID, e.UID}); err != nil { log.Fatalf("failed to write csv row: %v", err) } } w.Flush() if err := w.Error(); err != nil { log.Fatalf("csv flush error: %v", err) } fmt.Printf("Generated %d section enrollments to section_enrollments.csv\n", len(enrollments)) } func main() { data, err := os.ReadFile("config.json") if err != nil { log.Fatalf("failed to read config.json: %v", err) } var config Config if err := json.Unmarshal(data, &config); err != nil { log.Fatalf("failed to parse config.json: %v", err) } total := 0 for _, v := range config.PercentStatus { total += v } if total != 100 { log.Fatalf("percent_status values must total 100, got %d", total) } generated_users := GenerateUserData(config) SaveGeneratedUsers(generated_users) generated_sections := GenerateSectionData(config, generated_users) SaveGeneratedSections(generated_sections) generated_assignments := GenerateInstructorAssignmentData(generated_users, generated_sections) SaveInstructorsSections(generated_assignments) generated_enrollments := GenerateSectionEnrollmentData(generated_users, generated_sections, config) SaveGeneratedSectionEnrollments(generated_enrollments) } // uniqueNumericStrings generates n unique zero-padded numeric strings of the given digit length. func uniqueNumericStrings(digits, n int) []string { max := 1 for i := 0; i < digits; i++ { max *= 10 } if n > max { log.Fatalf("cannot generate %d unique %d-digit strings (max %d)", n, digits, max) } seen := make(map[int]struct{}, n) results := make([]string, 0, n) format := fmt.Sprintf("%%0%dd", digits) for len(results) < n { v := rand.Intn(max) if _, exists := seen[v]; !exists { seen[v] = struct{}{} results = append(results, fmt.Sprintf(format, v)) } } return results }