<commit_before>package faker

import (
	"bytes"
	"github.com/raitucarp/faker/locales"
	"math/rand"
	"reflect"
	"strconv"
	"strings"
	"text/template"
	"time"
)

func Fake(s string) (result string, err error) {
	s = strings.Replace(s, "#{", "#{sample ", -1)
	t := template.New("fake")
	t = t.Funcs(template.FuncMap{
		"sample": sample,
	})
	t = t.Delims("#{", "}")
	t, err = t.Parse(s)
	if err != nil {
		return
	}

	var b bytes.Buffer

	err = t.Execute(&b, data)
	if err != nil {
		return
	}

	return b.String(), nil
}

// get data from EN, and return error if not found
func defaultLocaleData(step ...string) (values []string) {
	immutable := reflect.ValueOf(defaultData)
	data := immutable.FieldByName(locales.EN).Interface()

	// field name length
	fieldLength := len(step) - 1

	for index, name := range step {

		immutable := reflect.ValueOf(data)
		val := immutable.FieldByName(name)

		if val.Kind().String() == "invalid" {
			return
		}

		if index == fieldLength {
			return val.Interface().([]string)
		} else {
			data = val.Interface()
		}
	}

	return
}

func round(val float64) int {
	if val < 0 {
		return int(val - 0.5)
	}
	return int(val + 0.5)
}

func getData(field ...string) (values []string) {
	// clone of data
	dat := data

	// field name length
	fieldLength := len(field) - 1

	// so far step
	var step []string

	// iterate field args
	for index, name := range field {
		step = append(step, name)
		immutable := reflect.ValueOf(dat)
		val := immutable.FieldByName(name)

		// try to get data from en locale
		if val.Kind().String() == "invalid" {
			d := defaultLocaleData(step...)

			// final decision, if not found
			// return zero slice
			if len(d) <= 0 {
				return
			} else {
				return d
			}
		}

		if index == fieldLength {
			return val.Interface().([]string)
		} else {
			dat = val.Interface()
		}
	}

	return
}

func sample(list []string) string {
	if len(list) <= 0 {
		return ""
	}

	listLength := len(list)
	nano := time.Now().UTC().UnixNano()
	rand.Seed(nano)
	firstName := rand.Perm(listLength)
	chosen := firstName[0]
	return list[chosen]
}

func replaceSymbolsWithNumber(s string, symbol rune) (result string) {
	for _, v := range s {
		if v == symbol {
			r := rand.Intn(9)
			result += strconv.Itoa(r)
		} else {
			result += string(v)
		}<commit_msg>refactor sample, add perm list for more random data<commit_after>package faker

import (
	"bytes"
	"github.com/raitucarp/faker/locales"
	"math/rand"
	"reflect"
	"strconv"
	"strings"
	"text/template"
	"time"
)

func Fake(s string) (result string, err error) {
	s = strings.Replace(s, "#{", "#{sample ", -1)
	t := template.New("fake")
	t = t.Funcs(template.FuncMap{
		"sample": sample,
	})
	t = t.Delims("#{", "}")
	t, err = t.Parse(s)
	if err != nil {
		return
	}

	var b bytes.Buffer

	err = t.Execute(&b, data)
	if err != nil {
		return
	}

	return b.String(), nil
}

// get data from EN, and return error if not found
func defaultLocaleData(step ...string) (values []string) {
	immutable := reflect.ValueOf(defaultData)
	data := immutable.FieldByName(locales.EN).Interface()

	// field name length
	fieldLength := len(step) - 1

	for index, name := range step {

		immutable := reflect.ValueOf(data)
		val := immutable.FieldByName(name)

		if val.Kind().String() == "invalid" {
			return
		}

		if index == fieldLength {
			return val.Interface().([]string)
		} else {
			data = val.Interface()
		}
	}

	return
}

func round(val float64) int {
	if val < 0 {
		return int(val - 0.5)
	}
	return int(val + 0.5)
}

func getData(field ...string) (values []string) {
	// clone of data
	dat := data

	// field name length
	fieldLength := len(field) - 1

	// so far step
	var step []string

	// iterate field args
	for index, name := range field {
		step = append(step, name)
		immutable := reflect.ValueOf(dat)
		val := immutable.FieldByName(name)

		// try to get data from en locale
		if val.Kind().String() == "invalid" {
			d := defaultLocaleData(step...)

			// final decision, if not found
			// return zero slice
			if len(d) <= 0 {
				return
			} else {
				return d
			}
		}

		if index == fieldLength {
			return val.Interface().([]string)
		} else {
			dat = val.Interface()
		}
	}

	return
}

func sample(list []string) string {
	if len(list) <= 0 {
		return ""
	}

	permList := permlist(list)
	chosen := permList[0]
	return list[chosen]
}

func permlist(list []string) []int {
	nano := time.Now().UTC().Second()
	rand.Seed(int64(nano) + int64(rand.Int()))
	permList := rand.Perm(len(list))
	return permList
}

func replaceSymbolsWithNumber(s string, symbol rune) (result string) {
	for _, v := range s {
		if v == symbol {
			r := rand.Intn(9)
			result += strconv.Itoa(r)
		} else {
			result += string(v)
		}
{'fraction_non_alphanumeric': 0.16129715981348028, 'fraction_numerical': 0.006782534972445952, 'mean_word_length': 3.054123711340206, 'pattern_counts': {'":': 2, '<': 9, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2907607', 'n_tokens_mistral': 1891, 'n_tokens_neox': 1735, 'n_words': 461}