func (g *Generator) Paragraph() string {
	count := g.Int(2, 10)
	sentences := make([]string, count)
	for i := 0; i < count; i++ {
		sentences[i] = g.Sentence()
	}
	return strings.Join(sentences, " ")
}
Paragraph generates a paragraph between 2 and 10 sentences.
package audit
import (
	"math/rand"
	"strings"
	"time"
	"unicode"
	"unicode/utf8"
)
var patterns = map[rune]string{
	'0': "0123456789",
	'1': "123456789",
	'o': "01234567",
	'O': "01234567",
	'h': "0123456789abcdef",
	'H': "0123456789ABCDEF",
	'a': "abcdefghijklmnopqrstuvwxyz",
	'A': "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
	'c': "bcdfghjklmnpqrstvwxyz",
	'C': "BCDFGHJKLMNPQRSTVWXYZ",
	'v': "aeiou",
	'V': "AEIOU",
	'z': "abcdefghijklmnopqrstuvwxyz0123456789",
	'Z': "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",
}
func SimpleRand() *rand.Rand {
	seed := time.Now().UnixNano()
	source := rand.NewSource(seed)
	return rand.New(source)
}
func FixedRand() *rand.Rand {
	source := rand.NewSource(42)
	return rand.New(source)
}
func ToUpperFirst(s string) string {
	if s == "" {
		return ""
	}
	r, n := utf8.DecodeRuneInString(s)
	return string(unicode.ToUpper(r)) + s[n:]
}
func BuildEMail(first, last, domain string) string {
	valid := make(map[rune]bool)
	for _, r := range "abcdefghijklmnopqrstuvwxyz0123456789-" {
		valid[r] = true
	}
	name := func(in string) string {
		out := []rune{}
		for _, r := range strings.ToLower(in) {
			if valid[r] {
				out = append(out, r)
			}
		}
		return string(out)
	}
	return name(first) + "." + name(last) + "@" + domain
}
func BuildTime(layout string, offset time.Duration) (string, time.Time) {
	t := time.Now().Add(offset)
	ts := t.Format(layout)
	tp, err := time.Parse(layout, ts)
	if err != nil {
		panic("cannot build time: " + err.Error())
	}
	return ts, tp
}
type Generator struct {
	rand *rand.Rand
}
func NewGenerator(rand *rand.Rand) *Generator {
	return &Generator{rand}
}
func (g *Generator) Int(lo, hi int) int {
	if lo == hi {
		return lo
	}
	if lo > hi {
		lo, hi = hi, lo
	}
	n := g.rand.Intn(hi - lo + 1)
	return lo + n
}
func (g *Generator) Ints(lo, hi, count int) []int {
	ints := make([]int, count)
	for i := 0; i < count; i++ {
		ints[i] = g.Int(lo, hi)
	}
	return ints
}
func (g *Generator) Percent() int {
	return g.Int(0, 100)
}
func (g *Generator) FlipCoin(percent int) bool {
	switch {
	case percent > 100:
		percent = 100
	case percent < 0:
		percent = 0
	}
	return g.Percent() >= percent
}
func (g *Generator) OneByteOf(values ...byte) byte {
	i := g.Int(0, len(values)-1)
	return values[i]
}
func (g *Generator) OneRuneOf(values string) rune {
	runes := []rune(values)
	i := g.Int(0, len(runes)-1)
	return runes[i]
}
func (g *Generator) OneIntOf(values ...int) int {
	i := g.Int(0, len(values)-1)
	return values[i]
}
func (g *Generator) OneStringOf(values ...string) string {
	i := g.Int(0, len(values)-1)
	return values[i]
}
func (g *Generator) OneDurationOf(values ...time.Duration) time.Duration {
	i := g.Int(0, len(values)-1)
	return values[i]
}
func (g *Generator) Word() string {
	return g.OneStringOf(words...)
}
func (g *Generator) Words(count int) []string {
	words := make([]string, count)
	for i := 0; i < count; i++ {
		words[i] = g.Word()
	}
	return words
}
func (g *Generator) LimitedWord(lo, hi int) string {
	length := g.Int(lo, hi)
	if length < MinWordLen {
		length = MinWordLen
	}
	if length > MaxWordLen {
		length = MaxWordLen
	}
	pos := g.Int(0, wordsLen)
	for {
		if pos >= wordsLen {
			pos = 0
		}
		if len(words[pos]) == length {
			return words[pos]
		}
		pos++
	}
}
func (g *Generator) Pattern(pattern string) string {
	result := []rune{}
	escaped := false
	for _, pr := range pattern {
		if !escaped {
			if pr == '^' {
				escaped = true
			} else {
				result = append(result, pr)
			}
			continue
		}
		ar := pr
		runes, ok := patterns[pr]
		if ok {
			ar = g.OneRuneOf(runes)
		}
		result = append(result, ar)
		escaped = false
	}
	return string(result)
}
func (g *Generator) Sentence() string {
	count := g.Int(2, 15)
	words := g.Words(count)
	words[0] = ToUpperFirst(words[0])
	for i := 2; i < count-1; i++ {
		if g.FlipCoin(80) {
			words[i] += ","
		}
	}
	return strings.Join(words, " ") + "."
}