faker.gno
7.84 Kb ยท 342 lines
1// Package faker provides fake data generation utilities for testing and
2// development purposes. It includes methods for generating names, addresses,
3// dates, emails, and other common data types using a pseudorandom generator.
4package faker
5
6import (
7 "math/rand"
8 "std"
9 "strconv"
10 "strings"
11 "unicode"
12
13 "gno.land/p/demo/entropy"
14 "gno.land/p/nt/ufmt"
15)
16
17// Faker provides fake data generation using a pseudorandom number generator.
18type Faker struct {
19 rng *rand.Rand
20}
21
22// NewGenerator creates a new Faker instance with a random seed.
23func NewGenerator() *Faker {
24 return NewGeneratorWithSeed(entropy.New().Value64())
25}
26
27// NewGeneratorWithSeed creates a new Faker instance with a specified seed.
28func NewGeneratorWithSeed(seed uint64) *Faker {
29 return &Faker{
30 rng: rand.New(rand.NewPCG(seed, 0xdeadbeef)),
31 }
32}
33
34// FirstName returns a random first name.
35func (f *Faker) FirstName() string {
36 return f.pickRandom(&FirstNames)
37}
38
39// LastName returns a random last name.
40func (f *Faker) LastName() string {
41 return f.pickRandom(&LastNames)
42}
43
44// FullName returns a random full name (first name + last name).
45func (f *Faker) FullName() string {
46 return f.FirstName() + " " + f.LastName()
47}
48
49// Age returns a random age between min and min+80.
50func (f *Faker) Age(min int) int {
51 return f.rng.IntN(80) + min
52}
53
54// City returns a random city name.
55func (f *Faker) City() string {
56 return f.pickRandom(&Cities)
57}
58
59// Country returns a random country name.
60func (f *Faker) Country() string {
61 return f.pickRandom(&Countries)
62}
63
64// Address returns a random address in the format "123 Street Name, City, Country".
65func (f *Faker) Address() string {
66 var (
67 streetNum = strconv.Itoa(f.rng.IntN(9999) + 1)
68 streetName = f.pickRandom(&StreetNames)
69 city = f.City()
70 country = f.Country()
71 )
72
73 return ufmt.Sprintf("%s %s, %s, %s", streetNum, streetName, city, country)
74}
75
76// Lorem returns random lorem ipsum text with the specified number of words.
77func (f *Faker) Lorem(wordCount int) string {
78 if wordCount <= 0 {
79 return ""
80 }
81
82 result := ""
83
84 for i := 0; i < wordCount; i++ {
85 if i > 0 {
86 result += " "
87 }
88 result += f.pickRandom(&LoremWords)
89 }
90
91 return result
92}
93
94// LoremSentence returns a random lorem ipsum sentence with 5-15 words.
95func (f *Faker) LoremSentence() string {
96 var (
97 wordCount = f.rng.IntN(10) + 5
98 sentence = f.Lorem(wordCount)
99 )
100
101 if len(sentence) > 0 {
102 sentence = string(sentence[0]-32) + sentence[1:] + "."
103 }
104
105 return sentence
106}
107
108// LoremParagraph returns a random lorem ipsum paragraph with 3-8 sentences.
109func (f *Faker) LoremParagraph() string {
110 var (
111 sentenceCount = f.rng.IntN(5) + 3
112 paragraph = ""
113 )
114
115 for i := 0; i < sentenceCount; i++ {
116 if i > 0 {
117 paragraph += " "
118 }
119 paragraph += f.LoremSentence()
120 }
121
122 return paragraph
123}
124
125// Date returns a random date in YYYY-MM-DD format between 1974 and 2025.
126func (f *Faker) Date() string {
127 var (
128 year = strconv.Itoa(f.rng.IntN(52) + 1974)
129 month = itoa2Digits(f.rng.IntN(12) + 1)
130 day = itoa2Digits(f.rng.IntN(28) + 1) // Don't bother handling month lengths
131 )
132
133 return ufmt.Sprintf("%s-%s-%s", year, month, day)
134}
135
136// Time returns a random time in HH:MM:SS format (24-hour).
137func (f *Faker) Time() string {
138 var (
139 hour = itoa2Digits(f.rng.IntN(24))
140 minute = itoa2Digits(f.rng.IntN(60))
141 second = itoa2Digits(f.rng.IntN(60))
142 )
143
144 return ufmt.Sprintf("%s:%s:%s", hour, minute, second)
145}
146
147// DateTime returns a random date and time in "YYYY-MM-DD HH:MM:SS" format.
148func (f *Faker) DateTime() string {
149 return f.Date() + " " + f.Time()
150}
151
152// Email returns a random email address in firstname.lastname@domain format.
153func (f *Faker) Email() string {
154 var (
155 firstName = strings.ToLower(f.FirstName())
156 lastName = strings.ToLower(f.LastName())
157 domain = f.pickRandom(&EmailDomains)
158 )
159
160 return ufmt.Sprintf("%s.%s@%s", firstName, lastName, domain)
161}
162
163// Phone returns a random phone number in (XXX) XXX-XXXX format.
164func (f *Faker) Phone() string {
165 var (
166 area = f.rng.IntN(900) + 100
167 exchange = f.rng.IntN(900) + 100
168 number = f.rng.IntN(10000)
169 )
170
171 return ufmt.Sprintf("(%d) %d-%d", area, exchange, number)
172}
173
174// StdAddress returns a random std.Address.
175func (f *Faker) StdAddress() std.Address {
176 var rawAddr std.RawAddress
177
178 for i := 0; i < std.RawAddressSize; i++ {
179 rawAddr[i] = byte(f.rng.IntN(256))
180 }
181
182 addr := std.EncodeBech32("g", rawAddr)
183
184 return std.Address(addr)
185}
186
187// Username returns a random gno username following the rules:
188// - Start with minimum 3 letters (lowercase)
189// - End with minimum 3 numbers
190// - Less than 20 chars total
191// - Only letters, numbers, and underscore allowed
192func (f *Faker) Username() string {
193 var (
194 username = ""
195 sources = []*[]string{
196 &FirstNames,
197 &LastNames,
198 &LoremWords,
199 }
200 )
201
202 for {
203 var (
204 source = sources[f.rng.IntN(len(sources))]
205 word = strings.ToLower(f.pickRandomLettersOnly(source))
206 next = username + word
207 )
208
209 if len(next) > 16 && len(username) > 3 {
210 break
211 } else if len(next) <= 16 {
212 username = next
213 }
214 }
215
216 for i := 0; i < 3; i++ {
217 username += strconv.Itoa(f.rng.IntN(10))
218 }
219
220 return username
221}
222
223func (f *Faker) pickRandom(source *[]string) string {
224 return (*source)[f.rng.IntN(len(*source))]
225}
226
227func (f *Faker) pickRandomLettersOnly(source *[]string) string {
228 isLettersOnly := func(s string) bool {
229 for _, r := range s {
230 if !unicode.IsLetter(r) {
231 return false
232 }
233 }
234 return true
235 }
236
237 // Limit attempts to 100 to avoid infinite loops.
238 for i := 0; i < 100; i++ {
239 word := f.pickRandom(source)
240 if isLettersOnly(word) {
241 return word
242 }
243 }
244
245 panic("could not find a letters-only word after 100 attempts")
246}
247
248func itoa2Digits(n int) string {
249 str := strconv.Itoa(n)
250 if n < 10 {
251 return "0" + str
252 }
253 return str
254}
255
256// defaultFaker is the default Faker instance used by package-level functions.
257var defaultFaker = NewGenerator()
258
259// FirstName returns a random first name using the default faker.
260func FirstName() string {
261 return defaultFaker.FirstName()
262}
263
264// LastName returns a random last name using the default faker.
265func LastName() string {
266 return defaultFaker.LastName()
267}
268
269// FullName returns a random full name using the default faker.
270func FullName() string {
271 return defaultFaker.FullName()
272}
273
274// Age returns a random age using the default faker.
275func Age(min int) int {
276 return defaultFaker.Age(min)
277}
278
279// City returns a random city name using the default faker.
280func City() string {
281 return defaultFaker.City()
282}
283
284// Country returns a random country name using the default faker.
285func Country() string {
286 return defaultFaker.Country()
287}
288
289// Address returns a random address using the default faker.
290func Address() string {
291 return defaultFaker.Address()
292}
293
294// Lorem returns random lorem ipsum text using the default faker.
295func Lorem(wordCount int) string {
296 return defaultFaker.Lorem(wordCount)
297}
298
299// LoremSentence returns a random lorem ipsum sentence using the default faker.
300func LoremSentence() string {
301 return defaultFaker.LoremSentence()
302}
303
304// LoremParagraph returns a random lorem ipsum paragraph using the default faker.
305func LoremParagraph() string {
306 return defaultFaker.LoremParagraph()
307}
308
309// Date returns a random date using the default faker.
310func Date() string {
311 return defaultFaker.Date()
312}
313
314// Time returns a random time using the default faker.
315func Time() string {
316 return defaultFaker.Time()
317}
318
319// DateTime returns a random date and time using the default faker.
320func DateTime() string {
321 return defaultFaker.DateTime()
322}
323
324// Email returns a random email address using the default faker.
325func Email() string {
326 return defaultFaker.Email()
327}
328
329// Phone returns a random phone number using the default faker.
330func Phone() string {
331 return defaultFaker.Phone()
332}
333
334// StdAddress returns a random std.Address using the default faker.
335func StdAddress() std.Address {
336 return defaultFaker.StdAddress()
337}
338
339// Username returns a random gno username using the default faker.
340func Username() string {
341 return defaultFaker.Username()
342}