From 78d0e5debe999701ca18f78f0759aa3142b51e1e Mon Sep 17 00:00:00 2001 From: Sky Johnson Date: Fri, 29 Aug 2025 07:14:29 -0500 Subject: [PATCH] move actions from town handlers to town actions file --- internal/actions/town.go | 92 +++++++++++++++++++++++++++++++++++++++ internal/routes/town.go | 93 +++------------------------------------- 2 files changed, 98 insertions(+), 87 deletions(-) create mode 100644 internal/actions/town.go diff --git a/internal/actions/town.go b/internal/actions/town.go new file mode 100644 index 0000000..baeb614 --- /dev/null +++ b/internal/actions/town.go @@ -0,0 +1,92 @@ +package actions + +import ( + "dk/internal/database" + "dk/internal/helpers" + "dk/internal/models/items" + "dk/internal/models/towns" + "dk/internal/models/users" + "fmt" + "maps" +) + +// RestAtInn handles the inn resting logic +func RestAtInn(user *users.User, town *towns.Town) error { + if user.Gold < town.InnCost { + return fmt.Errorf("you can't afford to stay here tonight") + } + + return database.Transaction(func() error { + return database.Update("users", map[string]any{ + "gold": user.Gold - town.InnCost, + "hp": user.MaxHP, + "mp": user.MaxMP, + "tp": user.MaxTP, + }, "id", user.ID) + }) +} + +// BuyShopItem handles purchasing an item from a town shop +func BuyShopItem(user *users.User, town *towns.Town, itemID int) error { + // Validate item exists in shop + if !town.HasShopItem(itemID) { + return fmt.Errorf("the item doesn't exist in this shop") + } + + // Get item details + item, err := items.Find(itemID) + if err != nil { + return fmt.Errorf("error purchasing item: %v", err) + } + + // Check user has enough gold + if user.Gold < item.Value { + return fmt.Errorf("you don't have enough gold to buy %s", item.Name) + } + + // Get equipment updates from existing actions + equipUpdates, err := UserEquipItem(user, item) + if err != nil { + return fmt.Errorf("cannot equip item: %v", err) + } + + // Execute purchase transaction + return database.Transaction(func() error { + // Start with gold deduction + updates := map[string]any{ + "gold": user.Gold - item.Value, + } + + // Add equipment updates + maps.Copy(updates, equipUpdates) + + return database.Update("users", updates, "id", user.ID) + }) +} + +// BuyTownMap handles purchasing a town map +func BuyTownMap(user *users.User, townID int) error { + // Get the town being mapped + mappedTown, err := towns.Find(townID) + if err != nil { + return fmt.Errorf("error purchasing map: %v", err) + } + + // Check user has enough gold + if user.Gold < mappedTown.MapCost { + return fmt.Errorf("you don't have enough gold to buy the map to %s", mappedTown.Name) + } + + // Get current town IDs and add new one + townIDs := user.GetTownIDs() + townIDs = append(townIDs, townID) + newTownsString := helpers.IntsToString(townIDs) + + // Execute purchase transaction + return database.Transaction(func() error { + return database.Update("users", map[string]any{ + "gold": user.Gold - mappedTown.MapCost, + "towns": newTownsString, + }, "id", user.ID) + }) +} diff --git a/internal/routes/town.go b/internal/routes/town.go index 6d52e00..485de71 100644 --- a/internal/routes/town.go +++ b/internal/routes/town.go @@ -3,9 +3,6 @@ package routes import ( "dk/internal/actions" "dk/internal/components" - "dk/internal/database" - "dk/internal/helpers" - "dk/internal/models/items" "dk/internal/models/towns" "dk/internal/models/users" "fmt" @@ -95,22 +92,9 @@ func rest(ctx sushi.Ctx) { town := ctx.UserValue("town").(*towns.Town) user := ctx.GetCurrentUser().(*users.User) - if user.Gold < town.InnCost { - sess.SetFlash("error", "You can't afford to stay here tonight.") - ctx.Redirect("/town/inn") - return - } - - err := database.Transaction(func() error { - return database.Update("users", map[string]any{ - "gold": user.Gold - town.InnCost, - "hp": user.MaxHP, - "mp": user.MaxMP, - "tp": user.MaxTP, - }, "id", user.ID) - }) + err := actions.RestAtInn(user, town) if err != nil { - sess.SetFlash("error", "Failed to rest at inn.") + sess.SetFlash("error", err.Error()) ctx.Redirect("/town/inn") return } @@ -144,54 +128,13 @@ func showShop(ctx sushi.Ctx) { func buyItem(ctx sushi.Ctx) { sess := ctx.GetCurrentSession() - id := ctx.Param("id").Int() - town := ctx.UserValue("town").(*towns.Town) - if !town.HasShopItem(id) { - sess.SetFlash("error", "The item doesn't exist in this shop.") - ctx.Redirect("/town/shop") - return - } - - item, err := items.Find(id) - if err != nil { - sess.SetFlash("error", "Error purchasing item; "+err.Error()) - ctx.Redirect("/town/shop") - return - } - user := ctx.GetCurrentUser().(*users.User) - if user.Gold < item.Value { - sess.SetFlash("error", "You don't have enough gold to buy "+item.Name) - ctx.Redirect("/town/shop") - return - } - // Get equipment updates from actions - equipUpdates, err := actions.UserEquipItem(user, item) + err := actions.BuyShopItem(user, town, id) if err != nil { - sess.SetFlash("error", "Cannot equip item: "+err.Error()) - ctx.Redirect("/town/shop") - return - } - - err = database.Transaction(func() error { - // Start with gold deduction - updates := map[string]any{ - "gold": user.Gold - item.Value, - } - - // Add equipment updates - for field, value := range equipUpdates { - updates[field] = value - } - - return database.Update("users", updates, "id", user.ID) - }) - - if err != nil { - sess.SetFlash("error", "Failed to purchase item.") + sess.SetFlash("error", err.Error()) ctx.Redirect("/town/shop") return } @@ -224,36 +167,12 @@ func showMaps(ctx sushi.Ctx) { func buyMap(ctx sushi.Ctx) { sess := ctx.GetCurrentSession() - id := ctx.Param("id").Int() - - mapped, err := towns.Find(id) - if err != nil { - sess.SetFlash("error", "Error purchasing map; "+err.Error()) - ctx.Redirect("/town/maps") - return - } - user := ctx.GetCurrentUser().(*users.User) - if user.Gold < mapped.MapCost { - sess.SetFlash("error", "You don't have enough gold to buy the map to "+mapped.Name) - ctx.Redirect("/town/maps") - return - } - - townIDs := user.GetTownIDs() - townIDs = append(townIDs, id) - newTownsString := helpers.IntsToString(townIDs) - - err = database.Transaction(func() error { - return database.Update("users", map[string]any{ - "gold": user.Gold - mapped.MapCost, - "towns": newTownsString, - }, "id", user.ID) - }) + err := actions.BuyTownMap(user, id) if err != nil { - sess.SetFlash("error", "Failed to purchase map.") + sess.SetFlash("error", err.Error()) ctx.Redirect("/town/maps") return }