package helpers import ( "fmt" "os" "strconv" "strings" ) // DynamicCompare compares two values dynamically and returns true if they are equal. // // Parameters: // // - s: The first value to compare. // // - u: The second value to compare. // // Returns: // // - bool: True if the values are equal, false otherwise. // // - error: An error if the values cannot be compared. func DynamicCompare(s interface{}, u interface{}) (bool, error) { switch t := s.(type) { case bool: u, ok := u.(bool) if !ok { return false, fmt.Errorf("[bool] cannot compare %T and %T, %v and %v", t, u, s, u) } return t == u, nil case string: u, ok := u.(string) if !ok { return false, fmt.Errorf("[string] cannot compare %T and %T, %v and %v", t, u, s, u) } return t == u, nil case int: u, ok := u.(int) if !ok { return false, fmt.Errorf("[int] cannot compare %T and %T, %v and %v", t, u, s, u) } return t == u, nil case float64: u, ok := u.(float64) // Log.Debug("[helpers] DynamicCompare", zap.Any("user", u), zap.Any("ok", ok), zap.Any("test_compare*(t==u)", t == u)) if t == u { return t == u, nil } if !ok { return false, fmt.Errorf("[float64] cannot compare %T and %T, %v and %v", t, u, s, u) } return t == u, nil case nil: return t == u, nil case []interface{}: for i := range t { if ok, err := DynamicCompare(t[i], u); err != nil { return false, err } else if !ok { return false, nil } } break case map[string]interface{}: for _, v := range t { if ok, err := DynamicCompare(v, u); err != nil { return false, err } else if !ok { return false, nil } } break default: return false, fmt.Errorf("[unknown] not in case. Cannot compare %T and %T, %v and %v", t, u, s, u) } if u == nil { return false, fmt.Errorf("[empty] the compared value is nil") } return false, fmt.Errorf("[unknown] unexpected error. [old] %v and [new] %v", s, u) } func GetTempFile(filename string, user string, suffix int) string { // Check if the temp file exist _, err := os.Stat(filename) // Log.Debug("[helpers] GetTempFile", zap.Any("filename", filename), zap.Any("suffix", suffix), zap.Any("err", err)) // file not exists if os.IsNotExist(err) { // Create temp file if suffix == 0 { return strings.Replace(filename, ".json", "_"+user+".tmp"+strconv.Itoa(suffix), 1) } // change extension from json to tmp filename = strings.Replace(filename, ".json", "_"+user+".tmp"+strconv.Itoa(suffix), 1) return filename } else { if strings.Contains(filename, ".tmp") { return GetTempFile(strings.Replace(filename, "_"+user+".tmp"+strconv.Itoa(suffix-1), "_"+user+".tmp"+strconv.Itoa(suffix), 1), user, suffix+1) } // recursive call return GetTempFile(strings.Replace(filename, ".json", "_"+user+".tmp"+strconv.Itoa(suffix), 1), user, suffix+1) } } // func PackTempToRealFile(data *data.Data, countryID string, filename string) { // // list file that end with .tmp* // files, err := filepath.Glob(filename + ".tmp*") // // for all files, read and get configNumber // if err != nil { // Log.Error("[helpers] PackTempToRealFile", zap.Error(err)) // } // // get configNumber from actual filename.json // // // base_recipe := data.GetRecipe(countryID, filename) // // read file and apply tmp file from 0 to tmpX. // // - if there is more than 1 user that access this file at the same time, // // pack in order, and if conflict, stop // if len(files) == 0 { // return // } // // TODO: must check the changes // for _, file := range files { // var tmpdata models.Recipe // tmpfile, err := os.Open(file) // if err != nil { // return // } // _ = json.NewDecoder(tmpfile).Decode(&tmpdata) // // apply change // // = tmpdata.Recipe01 // for key, val := range tmpdata.Recipe01 { // test_bol, err := DynamicCompare(base_recipe.Recipe01[key], val) // if err != nil { // Log.Error("[helpers] PackTempToRealFile", zap.Error(err)) // } // if !test_bol { // base_recipe.Recipe01[key] = val // } // } // } // // verify changes between tmpX and actual filename.json // // if changes, rename tmpX to filename (version +1) .json // }