forked from ebhomengo/niki
671 lines
20 KiB
Go
671 lines
20 KiB
Go
package gofakeit
|
||
|
||
import (
|
||
"fmt"
|
||
"strconv"
|
||
"strings"
|
||
|
||
"github.com/brianvoe/gofakeit/v7/data"
|
||
)
|
||
|
||
type ProductInfo struct {
|
||
Name string `json:"name" xml:"name"`
|
||
Description string `json:"description" xml:"description"`
|
||
Categories []string `json:"categories" xml:"categories"`
|
||
Price float64 `json:"price" xml:"price"`
|
||
Features []string `json:"features" xml:"features"`
|
||
Color string `json:"color" xml:"color"`
|
||
Material string `json:"material" xml:"material"`
|
||
UPC string `json:"upc" xml:"upc"`
|
||
Audience []string `json:"audience" xml:"audience"`
|
||
Dimension string `json:"dimension" xml:"dimension"`
|
||
UseCase string `json:"use_case" xml:"use_case"`
|
||
Benefit string `json:"benefit" xml:"benefit"`
|
||
Suffix string `json:"suffix" xml:"suffix"`
|
||
}
|
||
|
||
// Product will generate a random set of product information
|
||
func Product() *ProductInfo { return product(GlobalFaker) }
|
||
|
||
// Product will generate a random set of product information
|
||
func (f *Faker) Product() *ProductInfo { return product(f) }
|
||
|
||
func product(f *Faker) *ProductInfo {
|
||
// Categories
|
||
categories := []string{}
|
||
weightedCategory, _ := weighted(f, []any{1, 2, 3, 4}, []float32{1, 4, 3, 4})
|
||
|
||
for i := 0; i < weightedCategory.(int); i++ {
|
||
categories = append(categories, productCategory(f))
|
||
}
|
||
|
||
// Features
|
||
features := []string{}
|
||
for i := 0; i < number(f, 1, 5); i++ {
|
||
features = append(features, productFeature(f))
|
||
}
|
||
|
||
product := &ProductInfo{
|
||
Name: productName(f),
|
||
Description: productDescription(f),
|
||
Categories: categories,
|
||
Price: price(f, 3.00, 100.00),
|
||
UPC: productUPC(f),
|
||
Features: features,
|
||
Color: safeColor(f),
|
||
Material: productMaterial(f),
|
||
Audience: productAudience(f),
|
||
Dimension: productDimension(f),
|
||
UseCase: productUseCase(f),
|
||
Benefit: productBenefit(f),
|
||
Suffix: productSuffix(f),
|
||
}
|
||
|
||
return product
|
||
}
|
||
|
||
// ProductName will generate a random product name
|
||
func ProductName() string { return productName(GlobalFaker) }
|
||
|
||
// ProductName will generate a random product name
|
||
func (f *Faker) ProductName() string { return productName(f) }
|
||
|
||
func productName(f *Faker) string {
|
||
name := getRandValue(f, []string{"product", "name"})
|
||
adj := func() string { return getRandValue(f, []string{"product", "adjective"}) }
|
||
suf := func() string { return getRandValue(f, []string{"product", "suffix"}) }
|
||
mat := func() string { return productMaterial(f) }
|
||
feat := func() string { return productFeature(f) }
|
||
|
||
// Small realism helpers: occasional compound/connector without turning into a listing
|
||
compoundAdj := func() string {
|
||
// 1 in 5: "adj-adj" (e.g., "Ultra-Light", "Quick-Dry")
|
||
if number(f, 1, 5) == 1 {
|
||
return fmt.Sprintf("%s-%s", adj(), adj())
|
||
}
|
||
return adj()
|
||
}
|
||
|
||
// Keep it "product name"-ish: 2–3 chunks, no specs/colors/for-phrases.
|
||
// Weighted: 2-word names (~70%), 3-word names (~30%)
|
||
wordCount, _ := weighted(f, []any{"2word", "3word"}, []float32{70, 30})
|
||
|
||
switch wordCount {
|
||
case "2word":
|
||
// 2-word names (most common in real products)
|
||
switch number(f, 0, 4) {
|
||
case 0, 1:
|
||
// Adjective + Name (most common 2-word pattern)
|
||
return title(fmt.Sprintf("%s %s", compoundAdj(), name))
|
||
case 2:
|
||
// Name + Suffix
|
||
return title(fmt.Sprintf("%s %s", name, suf()))
|
||
case 3:
|
||
// Material + Name
|
||
return title(fmt.Sprintf("%s %s", mat(), name))
|
||
case 4:
|
||
// Feature + Name
|
||
return title(fmt.Sprintf("%s %s", feat(), name))
|
||
}
|
||
|
||
case "3word":
|
||
// 3-word names (less common)
|
||
switch number(f, 0, 4) {
|
||
case 0, 1:
|
||
// Adjective + Name + Suffix (most common 3-word pattern)
|
||
return title(fmt.Sprintf("%s %s %s", compoundAdj(), name, suf()))
|
||
case 2:
|
||
// Name + Feature + Suffix
|
||
return title(fmt.Sprintf("%s %s %s", name, feat(), suf()))
|
||
case 3:
|
||
// Adjective + Feature + Name
|
||
return title(fmt.Sprintf("%s %s %s", compoundAdj(), feat(), name))
|
||
case 4:
|
||
// Name + Material + Suffix
|
||
return title(fmt.Sprintf("%s %s %s", name, mat(), suf()))
|
||
}
|
||
}
|
||
|
||
// Fallback to 2-word name
|
||
return title(fmt.Sprintf("%s %s", compoundAdj(), name))
|
||
}
|
||
|
||
// ProductDescription will generate a random product description
|
||
func ProductDescription() string { return productDescription(GlobalFaker) }
|
||
|
||
// ProductDescription will generate a random product description
|
||
func (f *Faker) ProductDescription() string { return productDescription(f) }
|
||
|
||
func productDescription(f *Faker) string {
|
||
prodDesc := getRandValue(f, []string{"product", "description"})
|
||
|
||
// Replace all {productaudience} with join "and"
|
||
for strings.Contains(prodDesc, "{productaudience}") {
|
||
prodDesc = strings.Replace(prodDesc, "{productaudience}", strings.Join(productAudience(f), " and "), 1)
|
||
}
|
||
|
||
desc, _ := generate(f, prodDesc)
|
||
return desc
|
||
}
|
||
|
||
// ProductCategory will generate a random product category
|
||
func ProductCategory() string { return productCategory(GlobalFaker) }
|
||
|
||
// ProductCategory will generate a random product category
|
||
func (f *Faker) ProductCategory() string { return productCategory(f) }
|
||
|
||
func productCategory(f *Faker) string {
|
||
return getRandValue(f, []string{"product", "category"})
|
||
}
|
||
|
||
// ProductFeature will generate a random product feature
|
||
func ProductFeature() string { return productFeature(GlobalFaker) }
|
||
|
||
// ProductFeature will generate a random product feature
|
||
func (f *Faker) ProductFeature() string { return productFeature(f) }
|
||
|
||
func productFeature(f *Faker) string {
|
||
return getRandValue(f, []string{"product", "feature"})
|
||
}
|
||
|
||
// ProductMaterial will generate a random product material
|
||
func ProductMaterial() string { return productMaterial(GlobalFaker) }
|
||
|
||
// ProductMaterial will generate a random product material
|
||
func (f *Faker) ProductMaterial() string { return productMaterial(f) }
|
||
|
||
func productMaterial(f *Faker) string {
|
||
return getRandValue(f, []string{"product", "material"})
|
||
}
|
||
|
||
// ProductUPC will generate a random product UPC
|
||
func ProductUPC() string { return productUPC(GlobalFaker) }
|
||
|
||
// ProductUPC will generate a random product UPC
|
||
func (f *Faker) ProductUPC() string { return productUPC(f) }
|
||
|
||
func productUPC(f *Faker) string {
|
||
// The first digit of a UPC is a fixed digit (usually 0)
|
||
upc := "0"
|
||
|
||
// Generate the remaining 11 digits randomly
|
||
for i := 1; i < 12; i++ {
|
||
digit := number(f, 0, 9)
|
||
upc += fmt.Sprintf("%d", digit)
|
||
}
|
||
|
||
return upc
|
||
}
|
||
|
||
// ProductAudience will generate a random target audience
|
||
func ProductAudience() []string { return productAudience(GlobalFaker) }
|
||
|
||
// ProductAudience will generate a random target audience
|
||
func (f *Faker) ProductAudience() []string { return productAudience(f) }
|
||
|
||
func productAudience(f *Faker) []string {
|
||
audiences := []string{}
|
||
for i := 0; i < number(f, 1, 2); i++ {
|
||
// Check if the target audience is already in the list
|
||
// If it is, generate a new target audience
|
||
for {
|
||
audience := getRandValue(f, []string{"product", "target_audience"})
|
||
// Check if in array
|
||
if !stringInSlice(audience, audiences) {
|
||
audiences = append(audiences, audience)
|
||
break
|
||
}
|
||
}
|
||
}
|
||
return audiences
|
||
}
|
||
|
||
// ProductDimension will generate a random product dimension
|
||
func ProductDimension() string { return productDimension(GlobalFaker) }
|
||
|
||
// ProductDimension will generate a random product dimension
|
||
func (f *Faker) ProductDimension() string { return productDimension(f) }
|
||
|
||
func productDimension(f *Faker) string {
|
||
return getRandValue(f, []string{"product", "dimension"})
|
||
}
|
||
|
||
// ProductUseCase will generate a random product use case
|
||
func ProductUseCase() string { return productUseCase(GlobalFaker) }
|
||
|
||
// ProductUseCase will generate a random product use case
|
||
func (f *Faker) ProductUseCase() string { return productUseCase(f) }
|
||
|
||
func productUseCase(f *Faker) string {
|
||
return getRandValue(f, []string{"product", "use_case"})
|
||
}
|
||
|
||
// ProductBenefit will generate a random product benefit
|
||
func ProductBenefit() string { return productBenefit(GlobalFaker) }
|
||
|
||
// ProductBenefit will generate a random product benefit
|
||
func (f *Faker) ProductBenefit() string { return productBenefit(f) }
|
||
|
||
func productBenefit(f *Faker) string {
|
||
return getRandValue(f, []string{"product", "benefit"})
|
||
}
|
||
|
||
// ProductSuffix will generate a random product suffix
|
||
func ProductSuffix() string { return productSuffix(GlobalFaker) }
|
||
|
||
// ProductSuffix will generate a random product suffix
|
||
func (f *Faker) ProductSuffix() string { return productSuffix(f) }
|
||
|
||
func productSuffix(f *Faker) string {
|
||
return getRandValue(f, []string{"product", "suffix"})
|
||
}
|
||
|
||
// ProductISBN13 will generate a random ISBN-13 string for the product
|
||
func ProductISBN(opts *ISBNOptions) string { return productISBN(GlobalFaker, opts) }
|
||
|
||
// ProductISBN13 will generate a random ISBN-13 string for the product
|
||
func (f *Faker) ProductISBN(opts *ISBNOptions) string { return productISBN(f, opts) }
|
||
|
||
type ISBNOptions struct {
|
||
Version string // "10" or "13"
|
||
Separator string // e.g. "-", "" (default: "-")
|
||
}
|
||
|
||
func productISBN(f *Faker, opts *ISBNOptions) string {
|
||
if opts == nil {
|
||
opts = &ISBNOptions{Version: "13", Separator: "-"}
|
||
}
|
||
|
||
sep := opts.Separator
|
||
if sep == "" {
|
||
sep = "-"
|
||
}
|
||
|
||
// string of n random digits
|
||
randomDigits := func(f *Faker, n int) string {
|
||
digits := make([]byte, n)
|
||
for i := 0; i < n; i++ {
|
||
digits[i] = byte('0' + number(f, 0, 9))
|
||
}
|
||
return string(digits)
|
||
}
|
||
|
||
switch opts.Version {
|
||
case "10":
|
||
// ISBN-10 format: group(1)-registrant(4)-publication(3)-check(1)
|
||
group := randomDigits(f, 1)
|
||
registrant := randomDigits(f, 4)
|
||
publication := randomDigits(f, 3)
|
||
base := group + registrant + publication
|
||
|
||
// checksum
|
||
sum := 0
|
||
for i, c := range base {
|
||
digit := int(c - '0')
|
||
sum += digit * (10 - i)
|
||
}
|
||
remainder := (11 - (sum % 11)) % 11
|
||
check := "X"
|
||
if remainder < 10 {
|
||
check = strconv.Itoa(remainder)
|
||
}
|
||
|
||
return strings.Join([]string{group, registrant, publication, check}, sep)
|
||
|
||
case "13":
|
||
// ISBN-13 format: prefix(3)-group(1)-registrant(4)-publication(4)-check(1)
|
||
prefix := data.ISBN13Prefix
|
||
group := randomDigits(f, 1)
|
||
registrant := randomDigits(f, 4)
|
||
publication := randomDigits(f, 4)
|
||
base := prefix + group + registrant + publication
|
||
|
||
// checksum
|
||
sum := 0
|
||
for i, c := range base {
|
||
digit := int(c - '0')
|
||
if i%2 == 0 {
|
||
sum += digit
|
||
} else {
|
||
sum += digit * 3
|
||
}
|
||
}
|
||
remainder := (10 - (sum % 10)) % 10
|
||
check := strconv.Itoa(remainder)
|
||
|
||
return strings.Join([]string{prefix, group, registrant, publication, check}, sep)
|
||
|
||
default:
|
||
// fallback to ISBN-13 if invalid version provided
|
||
return productISBN(f, &ISBNOptions{Version: "13", Separator: sep})
|
||
}
|
||
}
|
||
|
||
func addProductLookup() {
|
||
AddFuncLookup("product", Info{
|
||
Display: "Product",
|
||
Category: "product",
|
||
Description: "An item created for sale or use",
|
||
Example: `{
|
||
"name": "olive copper monitor",
|
||
"description": "Backwards caused quarterly without week it hungry thing someone him regularly. Whomever this revolt hence from his timing as quantity us these yours.",
|
||
"categories": [
|
||
"clothing",
|
||
"tools and hardware"
|
||
],
|
||
"price": 7.61,
|
||
"features": [
|
||
"ultra-lightweight"
|
||
],
|
||
"color": "navy",
|
||
"material": "brass",
|
||
"upc": "012780949980",
|
||
"audience": [
|
||
"adults"
|
||
],
|
||
"dimension": "medium",
|
||
"use_case": "home",
|
||
"benefit": "comfort",
|
||
"suffix": "pro"
|
||
}`,
|
||
Output: "map[string]any",
|
||
ContentType: "application/json",
|
||
Aliases: []string{
|
||
"goods",
|
||
"merchandise",
|
||
"retail item",
|
||
"consumer product",
|
||
"commercial item",
|
||
},
|
||
Keywords: []string{
|
||
"sale", "use", "trade", "manufactured",
|
||
"market", "inventory", "supply", "distribution", "commodity",
|
||
},
|
||
Generate: func(f *Faker, m *MapParams, info *Info) (any, error) {
|
||
return product(f), nil
|
||
},
|
||
})
|
||
|
||
AddFuncLookup("productname", Info{
|
||
Display: "Product Name",
|
||
Category: "product",
|
||
Description: "Distinctive title or label assigned to a product for identification and marketing",
|
||
Example: "olive copper monitor",
|
||
Output: "string",
|
||
Aliases: []string{
|
||
"product title",
|
||
"product label",
|
||
"brand name",
|
||
"item name",
|
||
"product identifier",
|
||
},
|
||
Keywords: []string{
|
||
"product", "name", "title", "label", "brand",
|
||
"item", "merchandise", "goods", "article",
|
||
"identifier", "marketing", "branding",
|
||
"catalog", "inventory",
|
||
},
|
||
Generate: func(f *Faker, m *MapParams, info *Info) (any, error) {
|
||
return productName(f), nil
|
||
},
|
||
})
|
||
|
||
AddFuncLookup("productdescription", Info{
|
||
Display: "Product Description",
|
||
Category: "product",
|
||
Description: "Explanation detailing the features and characteristics of a product",
|
||
Example: "Backwards caused quarterly without week it hungry thing someone him regularly. Whomever this revolt hence from his timing as quantity us these yours.",
|
||
Output: "string",
|
||
Aliases: []string{
|
||
"product details",
|
||
"product specs",
|
||
"item description",
|
||
"feature list",
|
||
"marketing copy",
|
||
},
|
||
Keywords: []string{
|
||
"product", "description", "details", "features",
|
||
"specifications", "characteristics", "summary",
|
||
"overview", "attributes", "benefits",
|
||
"marketing", "content", "copy", "info", "text",
|
||
},
|
||
Generate: func(f *Faker, m *MapParams, info *Info) (any, error) {
|
||
return productDescription(f), nil
|
||
},
|
||
})
|
||
|
||
AddFuncLookup("productcategory", Info{
|
||
Display: "Product Category",
|
||
Category: "product",
|
||
Description: "Classification grouping similar products based on shared characteristics or functions",
|
||
Example: "clothing",
|
||
Output: "string",
|
||
Aliases: []string{
|
||
"product classification",
|
||
"product type",
|
||
"item category",
|
||
"product group",
|
||
"product segment",
|
||
},
|
||
Keywords: []string{
|
||
"product", "category", "type", "class", "classification",
|
||
"group", "segment", "line", "collection", "range",
|
||
"electronics", "furniture", "clothing", "appliances",
|
||
"food", "toys", "accessories", "goods",
|
||
},
|
||
Generate: func(f *Faker, m *MapParams, info *Info) (any, error) {
|
||
return productCategory(f), nil
|
||
},
|
||
})
|
||
|
||
AddFuncLookup("productfeature", Info{
|
||
Display: "Product Feature",
|
||
Category: "product",
|
||
Description: "Specific characteristic of a product that distinguishes it from others products",
|
||
Example: "ultra-lightweight",
|
||
Output: "string",
|
||
Aliases: []string{
|
||
"product trait",
|
||
"product attribute",
|
||
"key feature",
|
||
"unique feature",
|
||
"special characteristic",
|
||
},
|
||
Keywords: []string{
|
||
"feature", "trait", "attribute", "characteristic",
|
||
"capability", "functionality", "specification",
|
||
"benefit", "advantage", "highlight",
|
||
"unique", "differentiator",
|
||
},
|
||
Generate: func(f *Faker, m *MapParams, info *Info) (any, error) {
|
||
return productFeature(f), nil
|
||
},
|
||
})
|
||
|
||
AddFuncLookup("productmaterial", Info{
|
||
Display: "Product Material",
|
||
Category: "product",
|
||
Description: "The substance from which a product is made, influencing its appearance, durability, and properties",
|
||
Example: "brass",
|
||
Output: "string",
|
||
Aliases: []string{
|
||
"material type",
|
||
"product substance",
|
||
"product composition",
|
||
"item material",
|
||
"build material",
|
||
},
|
||
Keywords: []string{
|
||
"material", "substance", "composition", "make",
|
||
"fabric", "textile", "cloth", "leather", "wool",
|
||
"wood", "metal", "plastic", "glass", "stone",
|
||
"durability", "properties", "construction",
|
||
},
|
||
Generate: func(f *Faker, m *MapParams, info *Info) (any, error) {
|
||
return productMaterial(f), nil
|
||
},
|
||
})
|
||
|
||
AddFuncLookup("productupc", Info{
|
||
Display: "Product UPC",
|
||
Category: "product",
|
||
Description: "Standardized barcode used for product identification and tracking in retail and commerce",
|
||
Example: "012780949980",
|
||
Output: "string",
|
||
Aliases: []string{
|
||
"upc code",
|
||
"product barcode",
|
||
"product code",
|
||
"product sku",
|
||
"universal product code",
|
||
"retail barcode",
|
||
},
|
||
Keywords: []string{
|
||
"upc", "barcode", "product", "code", "identifier",
|
||
"sku", "retail", "commerce", "inventory",
|
||
"tracking", "scanning", "checkout", "label",
|
||
"universal", "standard",
|
||
},
|
||
Generate: func(f *Faker, m *MapParams, info *Info) (any, error) {
|
||
return productUPC(f), nil
|
||
},
|
||
})
|
||
|
||
AddFuncLookup("productaudience", Info{
|
||
Display: "Product Audience",
|
||
Category: "product",
|
||
Description: "The group of people for whom the product is designed or intended",
|
||
Example: "adults",
|
||
Output: "[]string",
|
||
Aliases: []string{
|
||
"target audience",
|
||
"target market",
|
||
"customer group",
|
||
"user base",
|
||
"demographic group",
|
||
},
|
||
Keywords: []string{
|
||
"audience", "market", "segment", "demographic",
|
||
"consumer", "customer", "buyer", "user",
|
||
"group", "target", "population", "adults",
|
||
"kids", "teens", "families", "professionals",
|
||
},
|
||
|
||
Generate: func(f *Faker, m *MapParams, info *Info) (any, error) {
|
||
return productAudience(f), nil
|
||
},
|
||
})
|
||
|
||
AddFuncLookup("productdimension", Info{
|
||
Display: "Product Dimension",
|
||
Category: "product",
|
||
Description: "The size or dimension of a product",
|
||
Example: "medium",
|
||
Output: "string",
|
||
Aliases: []string{
|
||
"product size",
|
||
"product measurement",
|
||
"item dimensions",
|
||
"product scale",
|
||
"size specification",
|
||
},
|
||
Keywords: []string{
|
||
"dimension", "size", "measurement", "proportion",
|
||
"scale", "specification", "specs", "length",
|
||
"width", "height", "depth", "volume", "weight",
|
||
"product", "item",
|
||
},
|
||
Generate: func(f *Faker, m *MapParams, info *Info) (any, error) {
|
||
return productDimension(f), nil
|
||
},
|
||
})
|
||
|
||
AddFuncLookup("productusecase", Info{
|
||
Display: "Product Use Case",
|
||
Category: "product",
|
||
Description: "The scenario or purpose for which a product is typically used",
|
||
Example: "home",
|
||
Output: "string",
|
||
Aliases: []string{
|
||
"use case",
|
||
"product purpose",
|
||
"intended use",
|
||
"product application",
|
||
"usage scenario",
|
||
},
|
||
Keywords: []string{
|
||
"use", "usecase", "purpose", "usage", "application",
|
||
"context", "scenario", "situation", "case",
|
||
"intention", "goal", "objective", "function",
|
||
"home", "office", "outdoor", "industrial", "commercial",
|
||
},
|
||
Generate: func(f *Faker, m *MapParams, info *Info) (any, error) {
|
||
return productUseCase(f), nil
|
||
},
|
||
})
|
||
|
||
AddFuncLookup("productbenefit", Info{
|
||
Display: "Product Benefit",
|
||
Category: "product",
|
||
Description: "The key advantage or value the product provides",
|
||
Example: "comfort",
|
||
Output: "string",
|
||
Aliases: []string{
|
||
"product advantage",
|
||
"product value",
|
||
"user benefit",
|
||
"customer gain",
|
||
"selling point",
|
||
},
|
||
Keywords: []string{
|
||
"benefit", "advantage", "value", "improvement",
|
||
"enhancement", "feature", "positive", "outcome",
|
||
},
|
||
Generate: func(f *Faker, m *MapParams, info *Info) (any, error) {
|
||
return productBenefit(f), nil
|
||
},
|
||
})
|
||
|
||
AddFuncLookup("productsuffix", Info{
|
||
Display: "Product Suffix",
|
||
Category: "product",
|
||
Description: "A suffix used to differentiate product models or versions",
|
||
Example: "pro",
|
||
Output: "string",
|
||
Aliases: []string{
|
||
"product suffix",
|
||
"model suffix",
|
||
"version suffix",
|
||
"edition suffix",
|
||
"name suffix",
|
||
},
|
||
Keywords: []string{
|
||
"suffix", "variant", "edition", "version", "model",
|
||
"series", "line", "tier", "release", "upgrade",
|
||
"plus", "pro", "max", "lite", "mini",
|
||
},
|
||
Generate: func(f *Faker, m *MapParams, info *Info) (any, error) {
|
||
return productSuffix(f), nil
|
||
},
|
||
})
|
||
|
||
AddFuncLookup("productisbn", Info{
|
||
Display: "Product ISBN",
|
||
Category: "product",
|
||
Description: "ISBN-10 or ISBN-13 identifier for books",
|
||
Example: "978-1-4028-9462-6",
|
||
Output: "string",
|
||
Aliases: []string{
|
||
"isbn code", "isbn number", "book isbn", "isbn13",
|
||
"isbn10", "publication code", "book identifier",
|
||
},
|
||
Keywords: []string{
|
||
"identifier", "publication", "library", "catalog",
|
||
"literature", "reference", "edition", "registration", "publishing",
|
||
},
|
||
Generate: func(f *Faker, m *MapParams, info *Info) (any, error) {
|
||
return productISBN(f, nil), nil
|
||
},
|
||
})
|
||
}
|