package data import ( "encoding/json" "log" "os" "path/filepath" "recipe-manager/models" "sort" "time" ) func readFile(version string) *models.Recipe { path := filepath.Join("cofffeemachineConfig", version) file, err := os.Open(path) if err != nil { log.Fatalf("Error when open file: %s", err) return nil } defer file.Close() var data *models.Recipe err = json.NewDecoder(file).Decode(&data) if err != nil { log.Fatalf("Error when decode file: %s", err) return nil } return data } type RecipeWithTimeStamps struct { Recipe models.Recipe TimeStamps int64 } type Data struct { CurrentVersion string AllVersions []string currentRecipe *models.Recipe recipeMap map[string]RecipeWithTimeStamps } func NewData() *Data { files, err := filepath.Glob("cofffeemachineConfig/coffeethai02_*.json") if err != nil { log.Panic("Error when scan recipe files:", err) } sort.Slice(files, func(i, j int) bool { file1, err := os.Stat(files[i]) if err != nil { log.Panic("Error when get file info:", err) } file2, err := os.Stat(files[j]) if err != nil { log.Panic("Error when get file info:", err) } return file1.ModTime().After(file2.ModTime()) }) for i := 0; i < len(files); i++ { files[i] = filepath.Base(files[i]) } defaultVersion := "coffeethai02_580.json" defaultRecipe := readFile(defaultVersion) return &Data{ CurrentVersion: defaultVersion, AllVersions: files, currentRecipe: defaultRecipe, recipeMap: map[string]RecipeWithTimeStamps{ defaultVersion: { Recipe: *defaultRecipe, TimeStamps: time.Now().Unix(), }, }, } } func (d *Data) GetRecipe(version string) models.Recipe { if version == "" || version == d.CurrentVersion { return *d.currentRecipe } log.Println("Change recipe to version:", version) if recipe, ok := d.recipeMap[version]; ok { d.CurrentVersion = version return recipe.Recipe } // change current version and read new recipe d.CurrentVersion = version d.currentRecipe = readFile(version) // save to map if len(d.recipeMap) > 5 { // limit keep in memory 5 version // remove oldest version var oldestVersion string var oldestTime int64 for k, v := range d.recipeMap { if oldestTime == 0 || v.TimeStamps < oldestTime { oldestTime = v.TimeStamps oldestVersion = k } } delete(d.recipeMap, oldestVersion) } d.recipeMap[version] = RecipeWithTimeStamps{ Recipe: *d.currentRecipe, TimeStamps: time.Now().Unix(), } return *d.currentRecipe } func (d *Data) GetRecipe01() []models.Recipe01 { return d.currentRecipe.Recipe01 } func (d *Data) GetMaterialSetting(version string) []models.MaterialSetting { result := make([]models.MaterialSetting, 0) if version == "" || version == d.CurrentVersion { copy(result, d.currentRecipe.MaterialSetting) return result } if recipe, ok := d.recipeMap[version]; ok { copy(result, recipe.Recipe.MaterialSetting) d.CurrentVersion = version return result } d.CurrentVersion = version d.currentRecipe = readFile(version) // save to map if len(d.recipeMap) > 5 { // limit keep in memory 5 version // remove oldest version var oldestVersion string var oldestTime int64 for k, v := range d.recipeMap { if oldestTime == 0 || v.TimeStamps < oldestTime { oldestTime = v.TimeStamps oldestVersion = k } } delete(d.recipeMap, oldestVersion) } d.recipeMap[version] = RecipeWithTimeStamps{ Recipe: *d.currentRecipe, TimeStamps: time.Now().Unix(), } copy(result, d.currentRecipe.MaterialSetting) return result } func (d *Data) GetMaterialCode(ids []uint64, version string) []models.MaterialCode { var result []models.MaterialCode if version == "" || version == d.CurrentVersion { result = d.currentRecipe.MaterialCode } else if recipe, ok := d.recipeMap[version]; ok { d.CurrentVersion = version return recipe.Recipe.MaterialCode } else { d.CurrentVersion = version d.currentRecipe = readFile(version) // save to map if len(d.recipeMap) > 5 { // limit keep in memory 5 version // remove oldest version var oldestVersion string var oldestTime int64 for k, v := range d.recipeMap { if oldestTime == 0 || v.TimeStamps < oldestTime { oldestTime = v.TimeStamps oldestVersion = k } } delete(d.recipeMap, oldestVersion) } d.recipeMap[version] = RecipeWithTimeStamps{ Recipe: *d.currentRecipe, TimeStamps: time.Now().Unix(), } result = d.currentRecipe.MaterialCode } if len(ids) == 0 { return result } resultFilter := make([]models.MaterialCode, len(ids)) for _, id := range ids { if id == 0 { continue } for _, m := range result { if m.MaterialID == id { resultFilter = append(resultFilter, m) break } } } return resultFilter }