github.com/easysoft/zendata@v0.0.0-20240513203326-705bd5a7fd67/internal/pkg/helper/value.go (about) 1 package helper 2 3 import ( 4 "fmt" 5 "math" 6 "reflect" 7 "strconv" 8 "strings" 9 10 consts "github.com/easysoft/zendata/internal/pkg/const" 11 commonUtils "github.com/easysoft/zendata/pkg/utils/common" 12 ) 13 14 func GenerateItems[TV ValType, TS StepType](start, end TV, step TS, 15 precision int, isRand bool, repeat int, repeatTag string, count int) ( 16 arr []interface{}) { 17 18 typ := GetType(start) 19 20 limit := getLimit(start, end, step, typ, isRand) 21 22 total := consts.MaxNumb 23 if count > 0 && count < total { 24 total = count 25 } 26 27 if repeatTag == "" { // repeat one by one 28 for i := int64(0); i < limit; i++ { 29 val := GetValue(start, step, precision, i, limit, isRand) 30 31 if IsFinish(val, end, step) { 32 break 33 } 34 35 RepeatSameVal(val, repeat, &arr) 36 37 if len(arr) > total { 38 break 39 } 40 } 41 } else if repeatTag == "!" { // repeat the list 42 for round := 0; round < repeat; round++ { 43 for i := int64(0); i < limit; i++ { 44 val := GetValue(start, step, precision, i, limit, isRand) 45 46 if IsFinish(val, end, step) { 47 break 48 } 49 50 arr = append(arr, val) 51 if len(arr) > total { 52 break 53 } 54 } 55 } 56 } 57 58 return 59 } 60 61 type ValType interface { 62 int64 | byte | float64 63 } 64 type StepType interface { 65 int64 | float64 66 } 67 68 func GetValue[TV ValType, TS StepType](start TV, step TS, precision int, it, limit int64, isRand bool) (ret TV) { 69 typ := GetType(start) 70 71 var val interface{} 72 73 if typ == "int" { 74 if !isRand { 75 val = int64(start) + it*int64(step) 76 } else { 77 rand := commonUtils.RandNum64(limit) 78 if step < 0 { 79 rand = rand * -1 80 } 81 82 val = int64(start) + rand 83 } 84 85 } else if typ == "char" { 86 if !isRand { 87 val = byte(start) + byte(int(it)*int(step)) 88 } else { 89 rand := commonUtils.RandNum(int(limit)) 90 if step < 0 { 91 rand = rand * -1 92 } 93 94 val = byte(start) + byte(rand) 95 } 96 } else if typ == "float" { 97 if !isRand { 98 valFloat := float64(start) + float64(it)*float64(step) 99 val = ChangePrecision(valFloat, precision) 100 } else { 101 rand := commonUtils.RandNum64(limit) 102 if step < 0 { 103 rand = rand * -1 104 } 105 106 val = float64(start) + float64(rand)*float64(step) 107 } 108 } 109 110 ret = val.(TV) 111 112 return 113 } 114 115 func IsFinish[TV ValType, TS StepType](a interface{}, b TV, step TS) bool { 116 typ := GetType(a) 117 118 if typ == "int" { 119 if (a.(int64) > int64(b) && step > 0) || (a.(int64) < int64(b) && step < 0) { 120 return true 121 } 122 } else if typ == "char" { 123 if (a.(byte) > byte(b) && step > 0) || (a.(byte) < byte(b) && step < 0) { 124 return true 125 } 126 127 } else if typ == "float" { 128 if (a.(float64) > float64(b) && step > 0) || (a.(float64) < float64(b) && step < 0) { 129 return true 130 } 131 } 132 133 return false 134 } 135 136 func getLimit[TV ValType, TS StepType](start TV, end TV, step TS, typ string, isRand bool) (limit int64) { 137 limit = int64(consts.MaxNumb) 138 139 if isRand { 140 if typ == "int" || typ == "char" { 141 limit = (int64(end) - int64(start)) / int64(step) 142 143 } else if typ == "float" { 144 limitFloat := (float64(end) - float64(start)) / float64(step) 145 limit = int64(math.Floor(limitFloat)) 146 } 147 148 //if limit > int64(consts.MaxNumb) { 149 // limit = int64(consts.MaxNumb) 150 //} 151 } 152 153 return 154 } 155 156 func RepeatSameVal[TV ValType](val TV, repeat int, arr *[]interface{}) { 157 for round := 0; round < repeat; round++ { 158 *arr = append(*arr, val) 159 160 if len(*arr) > consts.MaxNumb { 161 break 162 } 163 } 164 } 165 166 func GetType(value interface{}) string { 167 v := reflect.ValueOf(value) 168 169 switch v.Kind() { 170 case reflect.Int64: 171 return "int" 172 case reflect.Uint8: 173 return "char" 174 case reflect.Float64: 175 return "float" 176 default: 177 return "" 178 } 179 180 return "" 181 } 182 183 func GetPrecision(base float64, step interface{}) (precision int, newStep float64) { 184 baseStr := strconv.FormatFloat(base, 'f', -1, 64) 185 186 var stepFloat float64 = 1 187 188 switch step.(type) { 189 case float64: 190 stepFloat = step.(float64) 191 case int: 192 stepFloat = float64(step.(int)) 193 } 194 stepStr := strconv.FormatFloat(stepFloat, 'f', -1, 64) 195 196 baseIndex := strings.LastIndex(baseStr, ".") 197 stepIndex := strings.LastIndex(stepStr, ".") 198 199 if baseIndex < 0 { 200 baseIndex = 0 201 } 202 if stepIndex < 0 { 203 stepIndex = 0 204 } 205 206 baseWidth := len(baseStr) - baseIndex - 1 207 stepWidth := len(stepStr) - stepIndex - 1 208 209 if baseWidth > stepWidth { 210 precision = baseWidth 211 } else { 212 precision = stepWidth 213 } 214 215 if step == nil || step.(float64) == 0 { 216 newStep = float64(1) 217 for i := 0; i < precision; i++ { 218 newStep = newStep / 10 219 } 220 } else { 221 switch step.(type) { 222 case float64: 223 newStep = step.(float64) 224 case int: 225 newStep = float64(step.(int)) 226 } 227 } 228 229 return 230 } 231 232 func ChangePrecision(flt float64, precision int) float64 { 233 format := fmt.Sprintf("%%.%df", precision) 234 ret, _ := strconv.ParseFloat(fmt.Sprintf(format, flt), 64) 235 return ret 236 } 237 238 func InterfaceToStr(val interface{}) string { 239 str := consts.Na 240 241 switch val.(type) { 242 case int64: 243 str = strconv.FormatInt(val.(int64), 10) 244 case float64: 245 precision, _ := GetPrecision(val.(float64), 0) 246 str = strconv.FormatFloat(val.(float64), 'f', precision, 64) 247 case byte: 248 str = string(val.(byte)) 249 case string: 250 str = val.(string) 251 default: 252 } 253 return str 254 }