// Package randomdata implements a bunch of simple ways to generate (pseudo) random data package randomdata import ( "encoding/json" "fmt" "log" "math/rand" "net" "strconv" "strings" "time" "unicode" ) const ( Male int = 0 Female int = 1 RandomGender int = 2 ) const ( Small int = 0 Large int = 1 ) const ( FullCountry = 0 TwoCharCountry = 1 ThreeCharCountry = 2 ) const ( DateInputLayout = "2006-01-02" DateOutputLayout = "Monday 2 Jan 2006" ) type jsonContent struct { Adjectives []string `json:"adjectives"` Nouns []string `json:"nouns"` FirstNamesFemale []string `json:"firstNamesFemale"` FirstNamesMale []string `json:"firstNamesMale"` LastNames []string `json:"lastNames"` Domains []string `json:"domains"` People []string `json:"people"` StreetTypes []string `json:"streetTypes"` // Taken from https://github.com/tomharris/random_data/blob/master/lib/random_data/locations.rb Paragraphs []string `json:"paragraphs"` // Taken from feedbooks.com and www.gutenberg.org Countries []string `json:"countries"` // Fetched from the world bank at http://siteresources.worldbank.org/DATASTATISTICS/Resources/CLASS.XLS CountriesThreeChars []string `json:"countriesThreeChars"` CountriesTwoChars []string `json:"countriesTwoChars"` Currencies []string `json:"currencies"` //https://github.com/OpenBookPrices/country-data Cities []string `json:"cities"` States []string `json:"states"` StatesSmall []string `json:"statesSmall"` Days []string `json:"days"` Months []string `json:"months"` FemaleTitles []string `json:"femaleTitles"` MaleTitles []string `json:"maleTitles"` Timezones []string `json:"timezones"` // https://en.wikipedia.org/wiki/List_of_tz_database_time_zones Locales []string `json:"locales"` // https://tools.ietf.org/html/bcp47 UserAgents []string `json:"userAgents"` // http://techpatterns.com/downloads/firefox/useragentswitcher.xml CountryCallingCodes []string `json:"countryCallingCodes"` // from https://github.com/datasets/country-codes/blob/master/data/country-codes.csv ProvincesGB []string `json:"provincesGB"` StreetNameGB []string `json:"streetNameGB"` StreetTypesGB []string `json:"streetTypesGB"` } var jsonData = jsonContent{} var privateRand *rand.Rand func init() { privateRand = rand.New(rand.NewSource(time.Now().UnixNano())) jsonData = jsonContent{} err := json.Unmarshal(data, &jsonData) if err != nil { log.Fatal(err) } } func CustomRand(randToUse *rand.Rand) { privateRand = randToUse } // Returns a random part of a slice func randomFrom(source []string) string { return source[privateRand.Intn(len(source))] } // Title returns a random title, gender decides the gender of the name func Title(gender int) string { var title = "" switch gender { case Male: title = randomFrom(jsonData.MaleTitles) break case Female: title = randomFrom(jsonData.FemaleTitles) break default: title = FirstName(privateRand.Intn(2)) break } return title } // FirstName returns a random first name, gender decides the gender of the name func FirstName(gender int) string { var name = "" switch gender { case Male: name = randomFrom(jsonData.FirstNamesMale) break case Female: name = randomFrom(jsonData.FirstNamesFemale) break default: name = FirstName(rand.Intn(2)) break } return name } // LastName returns a random last name func LastName() string { return randomFrom(jsonData.LastNames) } // FullName returns a combination of FirstName LastName randomized, gender decides the gender of the name func FullName(gender int) string { return FirstName(gender) + " " + LastName() } // Email returns a random email func Email() string { return strings.ToLower(FirstName(RandomGender)+LastName()) + StringNumberExt(1, "", 3) + "@" + randomFrom(jsonData.Domains) } // Country returns a random country, countryStyle decides what kind of format the returned country will have func Country(countryStyle int64) string { country := "" switch countryStyle { default: case FullCountry: country = randomFrom(jsonData.Countries) break case TwoCharCountry: country = randomFrom(jsonData.CountriesTwoChars) break case ThreeCharCountry: country = randomFrom(jsonData.CountriesThreeChars) break } return country } // Currency returns a random currency under ISO 4217 format func Currency() string { return randomFrom(jsonData.Currencies) } // City returns a random city func City() string { return randomFrom(jsonData.Cities) } // ProvinceForCountry returns a randomly selected province (state, county,subdivision ) name for a supplied country. // If the country is not supported it will return an empty string. func ProvinceForCountry(countrycode string) string { switch countrycode { case "US": return randomFrom(jsonData.States) case "GB": return randomFrom(jsonData.ProvincesGB) } return "" } // State returns a random american state func State(typeOfState int) string { if typeOfState == Small { return randomFrom(jsonData.StatesSmall) } return randomFrom(jsonData.States) } // Street returns a random fake street name func Street() string { return fmt.Sprintf("%s %s", randomFrom(jsonData.People), randomFrom(jsonData.StreetTypes)) } // StreetForCountry returns a random fake street name typical to the supplied country. // If the country is not supported it will return an empty string. func StreetForCountry(countrycode string) string { switch countrycode { case "US": return Street() case "GB": return fmt.Sprintf("%s %s", randomFrom(jsonData.StreetNameGB), randomFrom(jsonData.StreetTypesGB)) } return "" } // Address returns an american style address func Address() string { return fmt.Sprintf("%d %s,\n%s, %s, %s", Number(100), Street(), City(), State(Small), PostalCode("US")) } // Paragraph returns a random paragraph func Paragraph() string { return randomFrom(jsonData.Paragraphs) } // Number returns a random number, if only one integer (n1) is supplied it returns a number in [0,n1) // if a second argument is supplied it returns a number in [n1,n2) func Number(numberRange ...int) int { nr := 0 if len(numberRange) > 1 { nr = 1 nr = privateRand.Intn(numberRange[1]-numberRange[0]) + numberRange[0] } else { nr = privateRand.Intn(numberRange[0]) } return nr } func Decimal(numberRange ...int) float64 { nr := 0.0 if len(numberRange) > 1 { nr = 1.0 nr = privateRand.Float64()*(float64(numberRange[1])-float64(numberRange[0])) + float64(numberRange[0]) } else { nr = privateRand.Float64() * float64(numberRange[0]) } if len(numberRange) > 2 { sf := strconv.FormatFloat(nr, 'f', numberRange[2], 64) nr, _ = strconv.ParseFloat(sf, 64) } return nr } func StringNumberExt(numberPairs int, separator string, numberOfDigits int) string { numberString := "" for i := 0; i < numberPairs; i++ { for d := 0; d < numberOfDigits; d++ { numberString += fmt.Sprintf("%d", Number(0, 9)) } if i+1 != numberPairs { numberString += separator } } return numberString } // StringNumber returns a random number as a string func StringNumber(numberPairs int, separator string) string { return StringNumberExt(numberPairs, separator, 2) } // StringSample returns a random string from a list of strings func StringSample(stringList ...string) string { str := "" if len(stringList) > 0 { str = stringList[Number(0, len(stringList))] } return str } func Boolean() bool { nr := privateRand.Intn(2) return nr != 0 } // Noun returns a random noun func Noun() string { return randomFrom(jsonData.Nouns) } // Adjective returns a random adjective func Adjective() string { return randomFrom(jsonData.Adjectives) } func uppercaseFirstLetter(word string) string { a := []rune(word) a[0] = unicode.ToUpper(a[0]) return string(a) } func lowercaseFirstLetter(word string) string { a := []rune(word) a[0] = unicode.ToLower(a[0]) return string(a) } // SillyName returns a silly name, useful for randomizing naming of things func SillyName() string { return uppercaseFirstLetter(Noun()) + Adjective() } // IpV4Address returns a valid IPv4 address as string func IpV4Address() string { blocks := []string{} for i := 0; i < 4; i++ { number := privateRand.Intn(255) blocks = append(blocks, strconv.Itoa(number)) } return strings.Join(blocks, ".") } // IpV6Address returns a valid IPv6 address as net.IP func IpV6Address() string { var ip net.IP for i := 0; i < net.IPv6len; i++ { number := uint8(privateRand.Intn(255)) ip = append(ip, number) } return ip.String() } // MacAddress returns an mac address string func MacAddress() string { blocks := []string{} for i := 0; i < 6; i++ { number := fmt.Sprintf("%02x", privateRand.Intn(255)) blocks = append(blocks, number) } return strings.Join(blocks, ":") } // Day returns random day func Day() string { return randomFrom(jsonData.Days) } // Month returns random month func Month() string { return randomFrom(jsonData.Months) } // FullDate returns full date func FullDate() string { timestamp := time.Now() year := timestamp.Year() month := Number(1, 13) maxDay := time.Date(year, time.Month(month+1), 0, 0, 0, 0, 0, time.UTC).Day() day := Number(1, maxDay+1) date := time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.UTC) return date.Format(DateOutputLayout) } // FullDateInRange returns a date string within a given range, given in the format "2006-01-02". // If no argument is supplied it will return the result of randomdata.FullDate(). // If only one argument is supplied it is treated as the max date to return. // If a second argument is supplied it returns a date between (and including) the two dates. // Returned date is in format "Monday 2 Jan 2006". func FullDateInRange(dateRange ...string) string { var ( min time.Time max time.Time duration int dateString string ) if len(dateRange) == 1 { max, _ = time.Parse(DateInputLayout, dateRange[0]) } else if len(dateRange) == 2 { min, _ = time.Parse(DateInputLayout, dateRange[0]) max, _ = time.Parse(DateInputLayout, dateRange[1]) } if !max.IsZero() && max.After(min) { duration = Number(int(max.Sub(min))) * -1 dateString = max.Add(time.Duration(duration)).Format(DateOutputLayout) } else if !max.IsZero() && !max.After(min) { dateString = max.Format(DateOutputLayout) } else { dateString = FullDate() } return dateString } func Timezone() string { return randomFrom(jsonData.Timezones) } func Locale() string { return randomFrom(jsonData.Locales) } func UserAgentString() string { return randomFrom(jsonData.UserAgents) } func PhoneNumber() string { str := randomFrom(jsonData.CountryCallingCodes) + " " str += Digits(privateRand.Intn(3) + 1) for { // max 15 chars remaining := 15 - (len(str) - strings.Count(str, " ")) if remaining < 2 { return "+" + str } str += " " + Digits(privateRand.Intn(remaining-1)+1) } }