Search Apps Documentation Source Content File Folder Download Copy Actions Download

faker.gno

7.86 Kb ยท 344 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	"crypto/bech32"
  8	"math/rand"
  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 chain.Address.
175func (f *Faker) StdAddress() address {
176	rawAddr := make([]byte, 32)
177	for i := 0; i < 32; i++ {
178		rawAddr[i] = byte(f.rng.IntN(32))
179	}
180
181	addr, err := bech32.Encode("g", rawAddr)
182	if err != nil {
183		panic(err)
184	}
185
186	return address(addr)
187}
188
189// Username returns a random gno username following the rules:
190// - Start with minimum 3 letters (lowercase)
191// - End with minimum 3 numbers
192// - Less than 20 chars total
193// - Only letters, numbers, and underscore allowed
194func (f *Faker) Username() string {
195	var (
196		username = ""
197		sources  = []*[]string{
198			&FirstNames,
199			&LastNames,
200			&LoremWords,
201		}
202	)
203
204	for {
205		var (
206			source = sources[f.rng.IntN(len(sources))]
207			word   = strings.ToLower(f.pickRandomLettersOnly(source))
208			next   = username + word
209		)
210
211		if len(next) > 16 && len(username) > 3 {
212			break
213		} else if len(next) <= 16 {
214			username = next
215		}
216	}
217
218	for i := 0; i < 3; i++ {
219		username += strconv.Itoa(f.rng.IntN(10))
220	}
221
222	return username
223}
224
225func (f *Faker) pickRandom(source *[]string) string {
226	return (*source)[f.rng.IntN(len(*source))]
227}
228
229func (f *Faker) pickRandomLettersOnly(source *[]string) string {
230	isLettersOnly := func(s string) bool {
231		for _, r := range s {
232			if !unicode.IsLetter(r) {
233				return false
234			}
235		}
236		return true
237	}
238
239	// Limit attempts to 100 to avoid infinite loops.
240	for i := 0; i < 100; i++ {
241		word := f.pickRandom(source)
242		if isLettersOnly(word) {
243			return word
244		}
245	}
246
247	panic("could not find a letters-only word after 100 attempts")
248}
249
250func itoa2Digits(n int) string {
251	str := strconv.Itoa(n)
252	if n < 10 {
253		return "0" + str
254	}
255	return str
256}
257
258// defaultFaker is the default Faker instance used by package-level functions.
259var defaultFaker = NewGenerator()
260
261// FirstName returns a random first name using the default faker.
262func FirstName() string {
263	return defaultFaker.FirstName()
264}
265
266// LastName returns a random last name using the default faker.
267func LastName() string {
268	return defaultFaker.LastName()
269}
270
271// FullName returns a random full name using the default faker.
272func FullName() string {
273	return defaultFaker.FullName()
274}
275
276// Age returns a random age using the default faker.
277func Age(min int) int {
278	return defaultFaker.Age(min)
279}
280
281// City returns a random city name using the default faker.
282func City() string {
283	return defaultFaker.City()
284}
285
286// Country returns a random country name using the default faker.
287func Country() string {
288	return defaultFaker.Country()
289}
290
291// Address returns a random address using the default faker.
292func Address() string {
293	return defaultFaker.Address()
294}
295
296// Lorem returns random lorem ipsum text using the default faker.
297func Lorem(wordCount int) string {
298	return defaultFaker.Lorem(wordCount)
299}
300
301// LoremSentence returns a random lorem ipsum sentence using the default faker.
302func LoremSentence() string {
303	return defaultFaker.LoremSentence()
304}
305
306// LoremParagraph returns a random lorem ipsum paragraph using the default faker.
307func LoremParagraph() string {
308	return defaultFaker.LoremParagraph()
309}
310
311// Date returns a random date using the default faker.
312func Date() string {
313	return defaultFaker.Date()
314}
315
316// Time returns a random time using the default faker.
317func Time() string {
318	return defaultFaker.Time()
319}
320
321// DateTime returns a random date and time using the default faker.
322func DateTime() string {
323	return defaultFaker.DateTime()
324}
325
326// Email returns a random email address using the default faker.
327func Email() string {
328	return defaultFaker.Email()
329}
330
331// Phone returns a random phone number using the default faker.
332func Phone() string {
333	return defaultFaker.Phone()
334}
335
336// StdAddress returns a random chain.Address using the default faker.
337func StdAddress() address {
338	return defaultFaker.StdAddress()
339}
340
341// Username returns a random gno username using the default faker.
342func Username() string {
343	return defaultFaker.Username()
344}