package recipes import ( "fmt" "sync" ) // RecipeManager provides high-level recipe system management with database integration type RecipeManager struct { db any // Placeholder for database connection masterRecipeList *MasterRecipeList masterRecipeBookList *MasterRecipeBookList loadedRecipes map[int32]*Recipe loadedRecipeBooks map[int32]*Recipe // Statistics stats RecipeManagerStats statisticsEnabled bool // Thread safety mu sync.RWMutex } // RecipeManagerStats contains statistics about recipe system operations type RecipeManagerStats struct { TotalRecipesLoaded int32 `json:"total_recipes_loaded"` TotalRecipeBooksLoaded int32 `json:"total_recipe_books_loaded"` LoadOperations int32 `json:"load_operations"` SaveOperations int32 `json:"save_operations"` ValidationErrors int32 `json:"validation_errors"` mu sync.RWMutex } // NewRecipeManager creates a new recipe manager with database integration func NewRecipeManager() *RecipeManager { return &RecipeManager{ db: nil, masterRecipeList: NewMasterRecipeList(), masterRecipeBookList: NewMasterRecipeBookList(), loadedRecipes: make(map[int32]*Recipe), loadedRecipeBooks: make(map[int32]*Recipe), statisticsEnabled: true, } } // containsComponent checks if a component ID exists in a slice func (rm *RecipeManager) containsComponent(components []int32, componentID int32) bool { for _, comp := range components { if comp == componentID { return true } } return false } // GetMasterRecipeList returns the master recipe list func (rm *RecipeManager) GetMasterRecipeList() *MasterRecipeList { return rm.masterRecipeList } // GetMasterRecipeBookList returns the master recipe book list func (rm *RecipeManager) GetMasterRecipeBookList() *MasterRecipeBookList { return rm.masterRecipeBookList } // GetRecipe returns a recipe by ID func (rm *RecipeManager) GetRecipe(recipeID int32) *Recipe { rm.mu.RLock() defer rm.mu.RUnlock() return rm.loadedRecipes[recipeID] } // GetRecipeBook returns a recipe book by ID func (rm *RecipeManager) GetRecipeBook(bookID int32) *Recipe { rm.mu.RLock() defer rm.mu.RUnlock() return rm.loadedRecipeBooks[bookID] } // GetStatistics returns current recipe system statistics func (rm *RecipeManager) GetStatistics() RecipeManagerStats { if !rm.statisticsEnabled { return RecipeManagerStats{} } rm.stats.mu.RLock() defer rm.stats.mu.RUnlock() // Return a copy without the mutex to avoid copying lock value return RecipeManagerStats{ TotalRecipesLoaded: rm.stats.TotalRecipesLoaded, TotalRecipeBooksLoaded: rm.stats.TotalRecipeBooksLoaded, LoadOperations: rm.stats.LoadOperations, SaveOperations: rm.stats.SaveOperations, ValidationErrors: rm.stats.ValidationErrors, // Note: deliberately omitting mu field to avoid copying lock } } // SetStatisticsEnabled enables or disables statistics collection func (rm *RecipeManager) SetStatisticsEnabled(enabled bool) { rm.mu.Lock() defer rm.mu.Unlock() rm.statisticsEnabled = enabled } // Validate performs comprehensive recipe system validation func (rm *RecipeManager) Validate() []string { rm.mu.RLock() defer rm.mu.RUnlock() var issues []string // Validate master recipe list if rm.masterRecipeList == nil { issues = append(issues, "master recipe list is nil") return issues } // Validate master recipe book list if rm.masterRecipeBookList == nil { issues = append(issues, "master recipe book list is nil") } // Check for recipes with invalid data for _, recipe := range rm.loadedRecipes { if recipe.ID == 0 { issues = append(issues, fmt.Sprintf("recipe has invalid ID: %s", recipe.Name)) } if recipe.Name == "" { issues = append(issues, fmt.Sprintf("recipe %d has empty name", recipe.ID)) } if recipe.Level < 0 || recipe.Level > 100 { issues = append(issues, fmt.Sprintf("recipe %d has invalid level: %d", recipe.ID, recipe.Level)) } if len(recipe.Products) != 5 { issues = append(issues, fmt.Sprintf("recipe %d has invalid products array length: %d", recipe.ID, len(recipe.Products))) } } return issues } // Size returns the total number of loaded recipes and recipe books func (rm *RecipeManager) Size() (recipes int32, recipeBooks int32) { rm.mu.RLock() defer rm.mu.RUnlock() return int32(len(rm.loadedRecipes)), int32(len(rm.loadedRecipeBooks)) }