You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

116 lines
2.8 KiB
Go

package main
import (
"encoding/csv"
"encoding/json"
"fmt"
"log"
"math/rand"
"os"
"github.com/brianvoe/gofakeit/v6"
)
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"`
}
type Config struct {
NumberOfUsers int `json:"number_of_users"`
PercentStatus map[string]int `json:"percent_status"`
}
var statuses = []string{"JD", "LLM", "MCL", "PHD", "SJD", "MLS", "SPEC", "MNR", "CERT"}
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)
}
// 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],
}
}
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", "FirstName", "LastName", "Status", "ExamID"}); 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}); 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", config.NumberOfUsers)
}
// 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
}