aboutsummaryrefslogtreecommitdiff
path: root/internal/action
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-06-19 18:20:26 -0400
committerhistoria <[not public]>2026-06-19 18:20:26 -0400
commit0ea4eec5dd2122c6704216971eb1249276297867 (patch)
tree430fbbef04e837820f1d031c190f52ecd6112e25 /internal/action
parent3a58125d14bb307f861b38c6c5b0a63babde7e08 (diff)
downloadthehouseoficarus-0ea4eec5dd2122c6704216971eb1249276297867.tar.gz
shop fixes, 'toggle' completely removed, movement speed increased
Diffstat (limited to 'internal/action')
-rw-r--r--internal/action/action.go23
-rw-r--r--internal/action/behavior.go6
-rw-r--r--internal/action/recipe.go110
-rw-r--r--internal/action/store.go107
4 files changed, 71 insertions, 175 deletions
diff --git a/internal/action/action.go b/internal/action/action.go
index 44f27f8..5e66708 100644
--- a/internal/action/action.go
+++ b/internal/action/action.go
@@ -1,5 +1,28 @@
package action
+import "strings"
+
+func WordPrefixMatch(input, name string) bool {
+ inputWords := strings.Fields(strings.ToLower(input))
+ if len(inputWords) == 0 {
+ return false
+ }
+ nameWords := strings.Fields(strings.ToLower(name))
+ for _, iw := range inputWords {
+ found := false
+ for _, nw := range nameWords {
+ if strings.HasPrefix(nw, iw) || strings.HasPrefix(iw, nw) {
+ found = true
+ break
+ }
+ }
+ if !found {
+ return false
+ }
+ }
+ return true
+}
+
type Action struct {
Type string
TargetID string
diff --git a/internal/action/behavior.go b/internal/action/behavior.go
index e1a79e3..4071f0d 100644
--- a/internal/action/behavior.go
+++ b/internal/action/behavior.go
@@ -91,9 +91,3 @@ type UseConfig struct {
Level int `yaml:"level"`
XP int `yaml:"xp"`
}
-
-type ToggleConfig struct {
- Message string `yaml:"message"`
- SetFlags map[string]any `yaml:"set_flags"`
- Check *Condition `yaml:"check"`
-}
diff --git a/internal/action/recipe.go b/internal/action/recipe.go
index d1acaa5..c1f30fb 100644
--- a/internal/action/recipe.go
+++ b/internal/action/recipe.go
@@ -1,7 +1,6 @@
package action
import (
- "fmt"
"os"
"path/filepath"
@@ -34,13 +33,52 @@ type RecipeDef struct {
type RecipeStore struct {
dataDir string
+ cache map[string][]RecipeDef
}
func NewRecipeStore(dataDir string) *RecipeStore {
- return &RecipeStore{dataDir: dataDir}
+ return &RecipeStore{dataDir: dataDir, cache: make(map[string][]RecipeDef)}
}
func (s *RecipeStore) LoadAll() ([]RecipeDef, error) {
+ return s.LoadByType("")
+}
+
+func (s *RecipeStore) LoadByType(recipeType string) ([]RecipeDef, error) {
+ if recipeType == "" {
+ recipeType = "_all"
+ }
+ if cached, ok := s.cache[recipeType]; ok {
+ result := make([]RecipeDef, len(cached))
+ copy(result, cached)
+ return result, nil
+ }
+
+ all, err := s.loadAllRaw()
+ if err != nil {
+ return nil, err
+ }
+
+ if recipeType == "_all" {
+ s.cache[recipeType] = all
+ result := make([]RecipeDef, len(all))
+ copy(result, all)
+ return result, nil
+ }
+
+ var filtered []RecipeDef
+ for _, r := range all {
+ if r.Type == recipeType {
+ filtered = append(filtered, r)
+ }
+ }
+ s.cache[recipeType] = filtered
+ result := make([]RecipeDef, len(filtered))
+ copy(result, filtered)
+ return result, nil
+}
+
+func (s *RecipeStore) loadAllRaw() ([]RecipeDef, error) {
dir := filepath.Join(s.dataDir, "recipes")
entries, err := os.ReadDir(dir)
if err != nil {
@@ -76,14 +114,11 @@ func (r *RecipeDef) MatchesEntry(itemID string) bool {
}
func (s *RecipeStore) FindByInput(recipeType string, itemID string) *RecipeDef {
- all, err := s.LoadAll()
+ all, err := s.LoadByType(recipeType)
if err != nil {
return nil
}
for i := range all {
- if recipeType != "" && all[i].Type != recipeType {
- continue
- }
for _, e := range all[i].Consume {
for _, id := range e.Items {
if id == itemID {
@@ -95,54 +130,9 @@ func (s *RecipeStore) FindByInput(recipeType string, itemID string) *RecipeDef {
return nil
}
-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()
+ all, err := s.LoadByType(recipeType)
if err != nil {
return nil, err
}
@@ -181,21 +171,7 @@ func (r *RecipeDef) EffectiveSkill() string {
return r.Type
}
-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 {
diff --git a/internal/action/store.go b/internal/action/store.go
index fd58281..a8db9df 100644
--- a/internal/action/store.go
+++ b/internal/action/store.go
@@ -5,107 +5,10 @@ import (
"math/rand"
"os"
"path/filepath"
- "sync"
"gopkg.in/yaml.v3"
)
-type Store struct {
- dataDir string
- mu sync.Mutex
- cache map[string]*RawBehavior
-}
-
-type RawBehavior struct {
- ID string
- Type string
- Raw map[string]any
-}
-
-func NewStore(dataDir string) *Store {
- return &Store{
- dataDir: dataDir,
- cache: make(map[string]*RawBehavior),
- }
-}
-
-func (s *Store) Load(id string) (*RawBehavior, error) {
- s.mu.Lock()
- if b, ok := s.cache[id]; ok {
- s.mu.Unlock()
- return b, nil
- }
- s.mu.Unlock()
-
- path := filepath.Join(s.dataDir, "behaviors", id+".yaml")
- data, err := os.ReadFile(path)
- if err != nil {
- return nil, fmt.Errorf("read behavior %s: %w", id, err)
- }
-
- var raw map[string]any
- if err := yaml.Unmarshal(data, &raw); err != nil {
- return nil, fmt.Errorf("parse behavior %s: %w", id, err)
- }
-
- rb := &RawBehavior{ID: id, Raw: raw}
- if t, ok := raw["type"].(string); ok {
- rb.Type = t
- }
- if rid, ok := raw["id"].(string); ok {
- rb.ID = rid
- }
-
- s.mu.Lock()
- s.cache[id] = rb
- s.mu.Unlock()
- return rb, nil
-}
-
-func unmarshalRaw[T any](rb *RawBehavior, expectedType string) (*T, error) {
- if rb.Type != expectedType {
- return nil, fmt.Errorf("behavior %s is type %s, expected %s", rb.ID, rb.Type, expectedType)
- }
- var cfg T
- raw, _ := yaml.Marshal(rb.Raw)
- if err := yaml.Unmarshal(raw, &cfg); err != nil {
- return nil, fmt.Errorf("parse %s config %s: %w", expectedType, rb.ID, err)
- }
- return &cfg, nil
-}
-
-func (s *Store) LoadGather(id string) (*GatherConfig, error) {
- rb, err := s.Load(id)
- if err != nil {
- return nil, err
- }
- return unmarshalRaw[GatherConfig](rb, "gather")
-}
-
-func (s *Store) LoadTalk(id string) (*TalkConfig, error) {
- rb, err := s.Load(id)
- if err != nil {
- return nil, err
- }
- return unmarshalRaw[TalkConfig](rb, "talk")
-}
-
-func (s *Store) LoadUse(id string) (*UseConfig, error) {
- rb, err := s.Load(id)
- if err != nil {
- return nil, err
- }
- return unmarshalRaw[UseConfig](rb, "use")
-}
-
-func (s *Store) LoadToggle(id string) (*ToggleConfig, error) {
- rb, err := s.Load(id)
- if err != nil {
- return nil, err
- }
- return unmarshalRaw[ToggleConfig](rb, "toggle")
-}
-
func SuccessChance(cfg SuccessFormula, level int, requiredLevel int) float64 {
chance := cfg.Base + float64(level-requiredLevel)*cfg.PerLevel
if chance > cfg.Cap {
@@ -117,8 +20,8 @@ func SuccessChance(cfg SuccessFormula, level int, requiredLevel int) float64 {
return chance
}
-func (s *Store) LoadDropTable(id string) (*DropTableDef, error) {
- path := filepath.Join(s.dataDir, "drops", id+".yaml")
+func LoadDropTable(dataDir, id string) (*DropTableDef, error) {
+ path := filepath.Join(dataDir, "drops", id+".yaml")
data, err := os.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("read drop table %s: %w", id, err)
@@ -130,7 +33,7 @@ func (s *Store) LoadDropTable(id string) (*DropTableDef, error) {
return &dt, nil
}
-func (s *Store) ResolveDrop(drops []DropEntry) *DropEntry {
+func ResolveDrop(dataDir string, drops []DropEntry) *DropEntry {
if len(drops) == 0 {
return nil
}
@@ -147,9 +50,9 @@ func (s *Store) ResolveDrop(drops []DropEntry) *DropEntry {
cumulative += drops[i].Weight
if roll < cumulative {
if drops[i].Table != "" {
- sub, err := s.LoadDropTable(drops[i].Table)
+ sub, err := LoadDropTable(dataDir, drops[i].Table)
if err == nil {
- if resolved := s.ResolveDrop(sub.Drops); resolved != nil {
+ if resolved := ResolveDrop(dataDir, sub.Drops); resolved != nil {
qty := drops[i].Quantity
if qty <= 0 {
qty = resolved.Quantity