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  }