154 lines
4.4 KiB
Go
154 lines
4.4 KiB
Go
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))
|
|
}
|