initial commit
commit
55bad627c2
@ -0,0 +1,2 @@
|
|||||||
|
config.json
|
||||||
|
users.csv
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
module maurer/user_data_generator
|
||||||
|
|
||||||
|
go 1.26.1
|
||||||
|
|
||||||
|
require github.com/brianvoe/gofakeit/v6 v6.28.0 // indirect
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
github.com/brianvoe/gofakeit/v6 v6.28.0 h1:Xib46XXuQfmlLS2EXRuJpqcw8St6qSZz75OUo0tgAW4=
|
||||||
|
github.com/brianvoe/gofakeit/v6 v6.28.0/go.mod h1:Xj58BMSnFqcn/fAQeSK+/PLtC5kSb7FJIq4JyGa8vEs=
|
||||||
@ -0,0 +1,115 @@
|
|||||||
|
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
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue