Compare commits

..

2 Commits

Author SHA1 Message Date
8f30fe7412 docs: update readme 2026-02-14 12:32:29 +01:00
1a051b594c fix: customize upvote ratio 2026-02-14 12:32:18 +01:00
2 changed files with 15 additions and 6 deletions

View File

@@ -256,6 +256,7 @@ Goyco includes a comprehensive CLI for administration:
# Database management # Database management
./bin/goyco migrate # Run database migrations ./bin/goyco migrate # Run database migrations
./bin/goyco seed database # Seed database with sample data ./bin/goyco seed database # Seed database with sample data
./bin/goyco seed database --posts 100 --users 10 --upvote-ratio 0.5 # Customize seeding
# User management # User management
./bin/goyco user create # Create new user ./bin/goyco user create # Create new user

View File

@@ -56,10 +56,11 @@ func runSeedCommand(userRepo repositories.UserRepository, postRepo repositories.
func printSeedUsage() { func printSeedUsage() {
fmt.Fprintln(os.Stderr, "Seed subcommands:") fmt.Fprintln(os.Stderr, "Seed subcommands:")
fmt.Fprintln(os.Stderr, " database [--posts <n>] [--users <n>] [--votes-per-post <n>]") fmt.Fprintln(os.Stderr, " database [--posts <n>] [--users <n>] [--votes-per-post <n>] [--upvote-ratio <r>]")
fmt.Fprintln(os.Stderr, " --posts: number of posts to create (default: 40)") fmt.Fprintln(os.Stderr, " --posts: number of posts to create (default: 40)")
fmt.Fprintln(os.Stderr, " --users: number of additional users to create (default: 5)") fmt.Fprintln(os.Stderr, " --users: number of additional users to create (default: 5)")
fmt.Fprintln(os.Stderr, " --votes-per-post: average votes per post (default: 15)") fmt.Fprintln(os.Stderr, " --votes-per-post: average votes per post (default: 15)")
fmt.Fprintln(os.Stderr, " --upvote-ratio: percentage of upvotes vs downvotes, 0.0-1.0 (default: 0.7)")
} }
func clampFlagValue(value *int, min int, name string) { func clampFlagValue(value *int, min int, name string) {
@@ -76,9 +77,10 @@ func seedDatabase(userRepo repositories.UserRepository, postRepo repositories.Po
numPosts := fs.Int("posts", 40, "number of posts to create") numPosts := fs.Int("posts", 40, "number of posts to create")
numUsers := fs.Int("users", 5, "number of additional users to create") numUsers := fs.Int("users", 5, "number of additional users to create")
votesPerPost := fs.Int("votes-per-post", 15, "average votes per post") votesPerPost := fs.Int("votes-per-post", 15, "average votes per post")
upvoteRatio := fs.Float64("upvote-ratio", 0.7, "percentage of upvotes vs downvotes, 0.0-1.0")
fs.SetOutput(os.Stderr) fs.SetOutput(os.Stderr)
fs.Usage = func() { fs.Usage = func() {
fmt.Fprintln(os.Stderr, "Usage: goyco seed database [--posts <n>] [--users <n>] [--votes-per-post <n>]") fmt.Fprintln(os.Stderr, "Usage: goyco seed database [--posts <n>] [--users <n>] [--votes-per-post <n>] [--upvote-ratio <r>]")
fmt.Fprintln(os.Stderr, "\nOptions:") fmt.Fprintln(os.Stderr, "\nOptions:")
fs.PrintDefaults() fs.PrintDefaults()
} }
@@ -93,6 +95,11 @@ func seedDatabase(userRepo repositories.UserRepository, postRepo repositories.Po
clampFlagValue(numUsers, 0, "users") clampFlagValue(numUsers, 0, "users")
clampFlagValue(numPosts, 1, "posts") clampFlagValue(numPosts, 1, "posts")
clampFlagValue(votesPerPost, 0, "votes-per-post") clampFlagValue(votesPerPost, 0, "votes-per-post")
if *upvoteRatio < 0 {
*upvoteRatio = 0
} else if *upvoteRatio > 1 {
*upvoteRatio = 1
}
if !IsJSONOutput() { if !IsJSONOutput() {
fmt.Println("Starting database seeding...") fmt.Println("Starting database seeding...")
@@ -119,7 +126,7 @@ func seedDatabase(userRepo repositories.UserRepository, postRepo repositories.Po
fmt.Printf("Seed user ready: ID=%d Username=%s\n", seedUser.ID, seedUser.Username) fmt.Printf("Seed user ready: ID=%d Username=%s\n", seedUser.ID, seedUser.Username)
} }
generator := newSeedGenerator(string(userPasswordHash)) generator := newSeedGenerator(string(userPasswordHash), *upvoteRatio)
allUsers := []database.User{*seedUser} allUsers := []database.User{*seedUser}
users, err := createUsers(generator, userRepo, *numUsers, "Creating users") users, err := createUsers(generator, userRepo, *numUsers, "Creating users")
@@ -258,13 +265,15 @@ func validateSeedConsistency(voteRepo repositories.VoteRepository, users []datab
type seedGenerator struct { type seedGenerator struct {
passwordHash string passwordHash string
randSource *rand.Rand randSource *rand.Rand
upvoteRatio float64
} }
func newSeedGenerator(passwordHash string) *seedGenerator { func newSeedGenerator(passwordHash string, upvoteRatio float64) *seedGenerator {
seed := time.Now().UnixNano() seed := time.Now().UnixNano()
return &seedGenerator{ return &seedGenerator{
passwordHash: passwordHash, passwordHash: passwordHash,
randSource: rand.New(rand.NewSource(seed)), randSource: rand.New(rand.NewSource(seed)),
upvoteRatio: upvoteRatio,
} }
} }
@@ -490,9 +499,8 @@ func (g *seedGenerator) createVotesForPost(voteRepo repositories.VoteRepository,
} }
usedUsers[user.ID] = true usedUsers[user.ID] = true
voteTypeInt := g.randSource.Intn(10)
var voteType database.VoteType var voteType database.VoteType
if voteTypeInt < 7 { if g.randSource.Float64() < g.upvoteRatio {
voteType = database.VoteUp voteType = database.VoteUp
} else { } else {
voteType = database.VoteDown voteType = database.VoteDown