Skip to content

Commit

Permalink
refactor: optimize genenerator function
Browse files Browse the repository at this point in the history
  • Loading branch information
Splode committed Apr 2, 2023
1 parent 78db39c commit 0875e13
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 50 deletions.
2 changes: 1 addition & 1 deletion cmd/fname/fname.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ func main() {

opts := []fname.GeneratorOption{}

c, err := fname.ParseCasing(casing)
c, err := fname.CasingFromString(casing)
if err != nil {
fmt.Fprintf(os.Stderr, "error: %s", err)
os.Exit(1)
Expand Down
101 changes: 55 additions & 46 deletions generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,40 @@ import (
"golang.org/x/text/language"
)

type Casing string
type Casing int

const (
Lower Casing = "lower"
Upper Casing = "upper"
Title Casing = "title"
Lower Casing = iota
Upper
Title
)

// Generator is a random name generator.
func (c Casing) String() string {
switch c {
case Lower:
return "lower"
case Upper:
return "upper"
case Title:
return "title"
default:
return "unknown"
}
}

func CasingFromString(casing string) (Casing, error) {
switch strings.ToLower(casing) {
case Lower.String():
return Lower, nil
case Upper.String():
return Upper, nil
case Title.String():
return Title, nil
default:
return -1, fmt.Errorf("invalid casing: %s", casing)
}
}

type Generator struct {
casing Casing
dict *Dictionary
Expand Down Expand Up @@ -47,7 +72,7 @@ func WithDelimiter(delimiter string) GeneratorOption {
// WithSeed sets the seed used to generate random numbers.
func WithSeed(seed int64) GeneratorOption {
return func(g *Generator) {
g.rand.Seed(seed)
g.rand = rand.New(rand.NewSource(seed))
}
}

Expand Down Expand Up @@ -75,59 +100,43 @@ func NewGenerator(opts ...GeneratorOption) *Generator {

// Generate generates a random name.
func (g *Generator) Generate() (string, error) {
// Keep generating adjective and noun pairs until they are not the same.
var adjective, noun string
for adjective == noun {
adjective = g.dict.adjectives[g.rand.Intn(g.dict.LengthAdjective())]
noun = g.dict.nouns[g.rand.Intn(g.dict.LengthNoun())]
if g.size < 2 || g.size > 4 {
return "", fmt.Errorf("invalid size: %d", g.size)
}

words := []string{adjective, noun}

switch g.size {
case 2:
// do nothing
case 3:
verb := g.dict.verbs[g.rand.Intn(g.dict.LengthVerb())]
words = append(words, verb)
case 4:
verb := g.dict.verbs[g.rand.Intn(g.dict.LengthVerb())]
words = append(words, verb)
adverb := g.dict.adverbs[g.rand.Intn(g.dict.LengthAdverb())]
words = append(words, adverb)
default:
return "", fmt.Errorf("invalid size: %d", g.size)
words := make([]string, 0, g.size)
adjectiveIndex := g.rand.Intn(g.dict.LengthAdjective())
nounIndex := g.rand.Intn(g.dict.LengthNoun())
for adjectiveIndex == nounIndex {
nounIndex = g.rand.Intn(g.dict.LengthNoun())
}
return strings.Join(g.applyCasing(words...), g.delimiter), nil
}

// ParseCasing parses a string into a casing.
func ParseCasing(casing string) (Casing, error) {
switch casing {
case "lower":
return Lower, nil
case "upper":
return Upper, nil
case "title":
return Title, nil
default:
return "", fmt.Errorf("invalid casing: %s", casing)
words = append(words, g.dict.adjectives[adjectiveIndex], g.dict.nouns[nounIndex])

if g.size >= 3 {
words = append(words, g.dict.verbs[g.rand.Intn(g.dict.LengthVerb())])
}
}

var titleCaser = cases.Title(language.English)
if g.size == 4 {
words = append(words, g.dict.adverbs[g.rand.Intn(g.dict.LengthAdverb())])
}

var casingMap = map[Casing]func(string) string{
Lower: strings.ToLower,
Upper: strings.ToUpper,
Title: titleCaser.String,
return strings.Join(g.applyCasing(words), g.delimiter), nil
}

func (g *Generator) applyCasing(words ...string) []string {
func (g *Generator) applyCasing(words []string) []string {
if fn, ok := casingMap[g.casing]; ok {
for i, word := range words {
words[i] = fn(word)
}
}
return words
}

var titleCaser = cases.Title(language.English)

var casingMap = map[Casing]func(string) string{
Lower: strings.ToLower,
Upper: strings.ToUpper,
Title: titleCaser.String,
}
6 changes: 3 additions & 3 deletions generator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ func TestGenerate(t *testing.T) {
}
}

func TestParseCasing(t *testing.T) {
func TestCasingFromString(t *testing.T) {
t.Log("Given the need to parse casing strings")
{
t.Log("\tWhen parsing a valid casing string")
Expand All @@ -199,7 +199,7 @@ func TestParseCasing(t *testing.T) {
{"title", Title},
}
for _, tc := range testCases {
c, err := ParseCasing(tc.name)
c, err := CasingFromString(tc.name)
if err != nil {
t.Fatalf("\t\tShould be able to parse a valid casing string : %v", err)
}
Expand All @@ -214,7 +214,7 @@ func TestParseCasing(t *testing.T) {

t.Log("\tWhen parsing an invalid casing string")
{
_, err := ParseCasing("invalid")
_, err := CasingFromString("invalid")
if err == nil {
t.Fatal("\t\tShould not be able to parse an invalid casing string")
}
Expand Down

0 comments on commit 0875e13

Please sign in to comment.