diff options
| author | historia <[not public]> | 2026-06-16 04:17:43 -0400 |
|---|---|---|
| committer | historia <[not public]> | 2026-06-16 04:17:43 -0400 |
| commit | 085e728d22a3369bd110b77409914cfbe9ebe611 (patch) | |
| tree | eeb88cb1ceb91cc9ea2b5a1877c3c66328fab503 /internal/action | |
| parent | 43f21aabae8924f35c12c8485e690aeefe0089fb (diff) | |
| download | thehouseoficarus-085e728d22a3369bd110b77409914cfbe9ebe611.tar.gz | |
feat: recipe system, combining items, cooking skill
Diffstat (limited to 'internal/action')
| -rw-r--r-- | internal/action/recipe.go | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/internal/action/recipe.go b/internal/action/recipe.go new file mode 100644 index 0000000..7627047 --- /dev/null +++ b/internal/action/recipe.go @@ -0,0 +1,213 @@ +package action + +import ( + "fmt" + "os" + "path/filepath" + + "gopkg.in/yaml.v3" +) + +type ConsumeEntry struct { + Items []string `yaml:"items"` + Qty int `yaml:"qty"` +} + +type RecipeDef struct { + ID string `yaml:"id"` + Type string `yaml:"type"` + Skill string `yaml:"skill"` + Level int `yaml:"level"` + XP int `yaml:"xp"` + Station []string `yaml:"station"` + Consume []ConsumeEntry `yaml:"consume"` + Output string `yaml:"output"` + Fail string `yaml:"fail"` + Message string `yaml:"message"` + FailMessage string `yaml:"fail_message"` + Wait float64 `yaml:"wait"` + Success *SuccessFormula `yaml:"success"` +} + +type RecipeStore struct { + dataDir string +} + +func NewRecipeStore(dataDir string) *RecipeStore { + return &RecipeStore{dataDir: dataDir} +} + +func (s *RecipeStore) LoadAll() ([]RecipeDef, error) { + dir := filepath.Join(s.dataDir, "recipes") + entries, err := os.ReadDir(dir) + if err != nil { + return nil, err + } + var recipes []RecipeDef + for _, e := range entries { + if e.IsDir() || filepath.Ext(e.Name()) != ".yaml" { + continue + } + data, err := os.ReadFile(filepath.Join(dir, e.Name())) + if err != nil { + continue + } + var r RecipeDef + if err := yaml.Unmarshal(data, &r); err != nil { + continue + } + recipes = append(recipes, r) + } + return recipes, nil +} + +func (r *RecipeDef) MatchesEntry(itemID string) bool { + for _, e := range r.Consume { + for _, id := range e.Items { + if id == itemID { + return true + } + } + } + return false +} + +func (s *RecipeStore) FindByItem(itemID, recipeType string) ([]RecipeDef, error) { + all, err := s.LoadAll() + if err != nil { + return nil, err + } + var matches []RecipeDef + for _, r := range all { + if recipeType != "" && r.Type != recipeType { + continue + } + if r.MatchesEntry(itemID) { + matches = append(matches, r) + } + } + return matches, nil +} + +func (s *RecipeStore) FindByItems(a, b string) ([]RecipeDef, error) { + all, err := s.LoadAll() + if err != nil { + return nil, err + } + var matches []RecipeDef + for _, r := range all { + if len(r.Consume) < 2 { + continue + } + aEntry := -1 + bEntry := -1 + for ei, e := range r.Consume { + for _, id := range e.Items { + if id == a && aEntry < 0 { + aEntry = ei + } + if id == b && bEntry < 0 { + bEntry = ei + } + } + } + if aEntry >= 0 && bEntry >= 0 && aEntry != bEntry { + matches = append(matches, r) + } + } + return matches, nil +} + +func (s *RecipeStore) FindByStation(itemID string, stationIDs []string, recipeType string) ([]RecipeDef, error) { + all, err := s.LoadAll() + if err != nil { + return nil, err + } + var matches []RecipeDef + for _, r := range all { + if recipeType != "" && r.Type != recipeType { + continue + } + if !r.MatchesEntry(itemID) { + continue + } + if len(r.Station) == 0 { + continue + } + for _, station := range stationIDs { + for _, rs := range r.Station { + if rs == station { + matches = append(matches, r) + goto next + } + } + } + next: + } + return matches, nil +} + +func (r *RecipeDef) DisplayName() string { + return r.Output +} + +func (s *RecipeStore) FindByNameOrID(query string, recipeType string) (*RecipeDef, error) { + all, err := s.LoadAll() + if err != nil { + return nil, err + } + for _, r := range all { + if recipeType != "" && r.Type != recipeType { + continue + } + if r.ID == query || r.Output == query { + return &r, nil + } + } + return nil, fmt.Errorf("recipe not found: %s", query) +} + +func (r *RecipeDef) FirstItemName(load func(string) (string, bool)) string { + for _, e := range r.Consume { + for _, id := range e.Items { + if name, ok := load(id); ok { + return name + } + return id + } + } + return "" +} + +func (r *RecipeDef) ConsumeAll(hasItem func(string) bool, removeItem func(string, int) bool) bool { + for _, e := range r.Consume { + found := false + for _, id := range e.Items { + if hasItem(id) { + removeItem(id, e.Qty) + found = true + break + } + } + if !found { + return false + } + } + return true +} + +func (r *RecipeDef) HasAllItems(hasItem func(string) bool) bool { + for _, e := range r.Consume { + found := false + for _, id := range e.Items { + if hasItem(id) { + found = true + break + } + } + if !found { + return false + } + } + return true +} |
