github.com/easysoft/zendata@v0.0.0-20240513203326-705bd5a7fd67/internal/pkg/service/field.go (about) 1 package service 2 3 import ( 4 "regexp" 5 "strconv" 6 "strings" 7 8 consts "github.com/easysoft/zendata/internal/pkg/const" 9 "github.com/easysoft/zendata/internal/pkg/domain" 10 "github.com/easysoft/zendata/pkg/utils/vari" 11 ) 12 13 type FieldService struct { 14 ResService *ResService `inject:""` 15 TextService *TextService `inject:""` 16 ValueService *ValueService `inject:""` 17 ArticleService *ArticleService `inject:""` 18 19 FixService *FixService `inject:""` 20 LoopService *LoopService `inject:""` 21 ListService *ListService `inject:""` 22 RangeService *RangeService `inject:""` 23 RandomService *RandomService `inject:""` 24 CombineService *CombineService `inject:""` 25 } 26 27 func (s *FieldService) Generate(field *domain.DefField, parentJoin bool) { 28 field.Join = field.Join || parentJoin 29 30 s.RangeService.DealwithFixRange(field) 31 32 // iterate children 33 if len(field.Fields) > 0 { 34 for i := range field.Fields { 35 if field.Fields[i].From == "" { 36 field.Fields[i].From = field.From 37 } 38 field.Fields[i].FileDir = field.FileDir 39 //field.Fields[i].ParentItems = field.Items 40 //field.Fields[i].ParentJoin = field.Join 41 42 s.Generate(&field.Fields[i], field.Join) 43 } 44 45 s.CombineService.CombineChildrenIfNeeded(field, parentJoin) 46 47 return 48 } 49 50 // generate values 51 if len(field.Froms) > 0 { // refer to multi res 52 s.GenValuesForMultiRes(field, true) 53 54 } else if field.From != "" && field.Type != consts.FieldTypeArticle { // refer to res 55 s.GenValuesForSingleRes(field) 56 57 } else if field.Config != "" { // refer to config 58 s.GenValuesForConfig(field) 59 60 } else { // not a refer 61 s.GenerateValuesForNoReferField(field) 62 } 63 64 // random values 65 if field.Rand && field.Type != consts.FieldTypeArticle { 66 field.Values = s.RandomService.RandomValues(field.Values) 67 } 68 69 if field.Use != "" && field.From == "" { 70 field.From = vari.GlobalVars.DefData.From 71 } 72 73 // 74 vari.GlobalVars.FieldNameToValuesMap[field.Field] = field.Values 75 vari.GlobalVars.FieldNameToFieldMap[field.Field] = *field 76 } 77 78 func (s *FieldService) GenerateValuesForNoReferField(field *domain.DefField) { 79 s.CreateField(field) 80 81 s.LoopService.ComputerLoopTimes(field) // change LoopStart, LoopEnd for conf like loop: 1-10 # 循环1次,2次…… 82 83 uniqueTotal := s.computerUniqueTotal(field) // computer total for array children(records: 3) OR range affixes (prefix: 1-3) 84 85 indexOfRow := 0 86 count := 0 87 values := make([]interface{}, 0) 88 89 for { 90 // 2. random replacement 91 isRandomAndLoopEnd := !vari.ResLoading && // ignore rand in resource 92 !(*field).ReferToAnotherYaml && 93 (*field).IsRand && (*field).LoopIndex > (*field).LoopEnd 94 // isNotRandomAndValOver := !(*field).IsRand && indexOfRow >= len(fieldWithValues.Values) 95 if count >= uniqueTotal || isRandomAndLoopEnd { // || count >= vari.GlobalVars.Total 96 for _, v := range field.Values { 97 v = s.FixService.AddFix(v, field, count, true) 98 99 values = append(values, v) 100 } 101 break 102 } 103 104 // 处理格式、前后缀、loop等 105 val := s.LoopService.LoopFieldValueToSingleStr(field, &indexOfRow, count, true) 106 values = append(values, val) 107 108 count++ 109 110 if count >= uniqueTotal { // { || count >= vari.GlobalVars.Total{ 111 break 112 } 113 114 (*field).LoopIndex = (*field).LoopIndex + 1 115 if (*field).LoopIndex > (*field).LoopEnd { 116 (*field).LoopIndex = (*field).LoopStart 117 } 118 } 119 120 field.Values = values 121 122 return 123 } 124 125 func (s *FieldService) CreateField(field *domain.DefField) { 126 if field.Type == "" { // set default 127 field.Type = consts.FieldTypeList 128 } 129 if field.Length > 0 { 130 // field.Length = field.Length - len(field.Prefix) - len(field.Postfix) 131 if field.Length < 0 { 132 field.Length = 0 133 } 134 } 135 136 if field.Type == consts.FieldTypeList { 137 s.ListService.CreateListFieldValues(field) 138 } else if field.Type == consts.FieldTypeArticle { 139 s.ArticleService.CreateArticleField(field) 140 141 } else if field.Type == consts.FieldTypeTimestamp { 142 s.ValueService.CreateTimestampField(field) 143 } 144 145 return 146 } 147 148 func (s *FieldService) GenValuesForConfig(field *domain.DefField) (values []interface{}) { 149 groupValues := vari.GlobalVars.ResData[field.Config] 150 151 field.Values = groupValues["all"] 152 153 s.LoopService.LoopAndFixFieldValues(field, true) 154 155 return 156 } 157 158 func (s *FieldService) GenValuesForSingleRes(field *domain.DefField) { 159 if field.Use != "" { // refer to ranges or instance 160 key := s.ResService.GetFromKey(field) 161 groupValues := vari.GlobalVars.ResData[key] 162 163 uses := strings.TrimSpace(field.Use) // like group{limit:repeat} 164 use, numLimit, repeat := s.getNum(uses) 165 166 if strings.Index(use, "all") == 0 { 167 valuesForAdd := s.getRepeatValuesFromAll(groupValues, numLimit, repeat) 168 field.Values = append(field.Values, valuesForAdd...) 169 } else { 170 infos := s.parseUse(uses) 171 valuesForAdd := s.getRepeatValuesFromGroups(groupValues, infos) 172 field.Values = append(field.Values, valuesForAdd...) 173 } 174 175 } else if field.Select != "" { // refer to excel 176 groupValues := vari.GlobalVars.ResData[s.ResService.GetFromKey(field)] 177 resKey := field.Select 178 179 // deal with the key 180 if vari.GlobalVars.DefData.Type == consts.DefTypeArticle { 181 resKey = resKey + "_" + field.Field 182 } 183 184 field.Values = append(field.Values, groupValues[resKey]...) 185 } 186 187 s.LoopService.LoopAndFixFieldValues(field, true) 188 189 return 190 } 191 192 func (s *FieldService) GenValuesForMultiRes(field *domain.DefField, withFix bool) { 193 unionValues := make([]interface{}, 0) // 2 dimension arr for from, [ [a,b,c], [1,2,3] ] 194 195 // multi froms 1. 196 for _, from := range field.Froms { 197 if from.From == "" { 198 from.From = field.From 199 } 200 201 from.FileDir = field.FileDir 202 203 s.Generate(&from, true) 204 205 unionValues = append(unionValues, from.Values...) 206 } 207 208 count := len(unionValues) 209 if count > vari.GlobalVars.Total { 210 count = vari.GlobalVars.Total 211 } 212 213 field.Values = unionValues 214 215 s.LoopService.LoopAndFixFieldValues(field, true) 216 217 return 218 } 219 220 func (s *FieldService) getRepeatValuesFromAll(groupValues map[string][]interface{}, numLimit, repeat int) (ret []interface{}) { 221 if repeat == 0 { 222 repeat = 1 223 } 224 225 count := 0 226 exit: 227 for _, arr := range groupValues { 228 for _, item := range arr { 229 for i := 0; i < repeat; i++ { 230 ret = append(ret, item) 231 count++ 232 233 if numLimit > 0 && count >= numLimit { 234 break exit 235 } 236 } 237 } 238 } 239 240 return 241 } 242 243 func (s *FieldService) getRepeatValuesFromGroups(groupValues map[string][]interface{}, info []retsInfo) (ret []interface{}) { 244 count := 0 245 246 exit: 247 for _, v := range info { 248 if v.repeat == 0 { 249 v.repeat = 1 250 } 251 252 arr := groupValues[v.ret] 253 if len(arr) == 0 { 254 break exit 255 } 256 if v.numLimit != 0 { // privateB{n} 257 for i := 0; (v.numLimit > 0 && i < v.numLimit) && i < len(arr) && i < vari.GlobalVars.Total; i++ { 258 index := i / v.repeat 259 ret = append(ret, arr[index]) 260 count++ 261 } 262 } else { // privateA 263 for i := 0; i < len(arr) && i < vari.GlobalVars.Total; i++ { 264 index := i / v.repeat % len(arr) 265 ret = append(ret, arr[index]) 266 count++ 267 } 268 } 269 270 if count >= vari.GlobalVars.Total { 271 break exit 272 } 273 274 } 275 return 276 } 277 278 func (s *FieldService) computerUniqueTotal(field *domain.DefField) (ret int) { 279 ret = len(field.Values) 280 281 if field.PostfixRange != nil && len(field.PostfixRange.Values) > 0 { 282 ret *= len(field.PostfixRange.Values) 283 } 284 285 if field.PrefixRange != nil && len(field.PrefixRange.Values) > 0 { 286 ret *= len(field.PrefixRange.Values) 287 } 288 289 if ret < len(field.Values) { 290 ret = len(field.Values) 291 } 292 293 return 294 } 295 296 func (s *FieldService) getNum(group string) (ret string, numLimit, repeat int) { 297 regx := regexp.MustCompile(`\{([^:]*):?([^:]*)\}`) 298 arr := regx.FindStringSubmatch(group) 299 if len(arr) >= 2 { 300 numLimit, _ = strconv.Atoi(arr[1]) 301 } 302 if len(arr) >= 3 { 303 repeat, _ = strconv.Atoi(arr[2]) 304 } 305 306 ret = regx.ReplaceAllString(group, "") 307 308 return 309 } 310 311 // pars Uses 312 type retsInfo struct { 313 ret string 314 numLimit int 315 repeat int 316 } 317 318 func (s *FieldService) parseUse(groups string) (results []retsInfo) { 319 rets := strings.Split(groups, ",") 320 results = make([]retsInfo, len(rets)) 321 regx := regexp.MustCompile(`\{([^:]*):?([^:]*)\}`) 322 for k, v := range rets { 323 results[k].ret = regx.ReplaceAllString(v, "") 324 arr := regx.FindStringSubmatch(v) 325 if len(arr) >= 2 { 326 results[k].numLimit, _ = strconv.Atoi(arr[1]) 327 } 328 if len(arr) >= 3 { 329 results[k].repeat, _ = strconv.Atoi(arr[2]) 330 if results[k].repeat == 0 { 331 results[k].repeat = 1 332 } 333 } 334 } 335 return 336 }