From d6d3dc9f44905c8e109edb8215f96892b6adfb3f Mon Sep 17 00:00:00 2001 From: Jose Henrique Date: Sat, 1 Feb 2025 13:50:39 -0300 Subject: [PATCH] Refactor pet action management: rename PetAction to PetActionGather, update related models and services, and enhance resource gathering logic. --- Controllers/PetController.cs | 82 ++++++++++++- Models/Pet.cs | 3 +- Models/{PetAction.cs => PetActionGather.cs} | 8 ++ Models/PetClassInfo.cs | 19 ++- Models/PetUpdateActionRequest.cs | 3 +- Program.cs | 2 + Repositories/PetClassRepository.cs | 121 ++++++++++++++++++++ Repositories/PetRepository.cs | 38 +++--- Services/PetClassService.cs | 47 ++++++++ Services/PetService.cs | 50 +++++++- pet-companion-api.http | 6 - 11 files changed, 350 insertions(+), 29 deletions(-) rename Models/{PetAction.cs => PetActionGather.cs} (61%) create mode 100644 Repositories/PetClassRepository.cs create mode 100644 Services/PetClassService.cs delete mode 100644 pet-companion-api.http diff --git a/Controllers/PetController.cs b/Controllers/PetController.cs index 2c921c2..d36734a 100644 --- a/Controllers/PetController.cs +++ b/Controllers/PetController.cs @@ -9,13 +9,18 @@ namespace pet_companion_api.Controllers public class PetController : ControllerBase { private readonly PetService petService; + private readonly PetClassService petClassService; private readonly ILogger logger; private Guid userId = Guid.Parse("f5f4b3b3-3b7b-4b7b-8b7b-7b7b7b7b7b7b"); - public PetController(ILogger logger, PetService petService) + public PetController( + ILogger logger, + PetService petService, + PetClassService petClassService) { this.logger = logger; this.petService = petService; + this.petClassService = petClassService; } [HttpGet("")] @@ -31,8 +36,45 @@ namespace pet_companion_api.Controllers return CreatedAtAction(nameof(GetAllPets), new { id = createdPet.Id }, createdPet); } - [HttpPut("{petId}/action")] - public IActionResult UpdatePetAction(string petId, [FromBody] PetUpdateActionRequest actionRequest) + /// + /// + /// + /// + /// One of `feed`, `play`, `sleep` + /// + [HttpPut("{petId}/action/{action}")] + public IActionResult UpdatePetAction(string petId, string action) + { + try + { + PetAction petAction; + switch (action.ToLower()) + { + case "feed": + petAction = PetAction.FEED; + break; + case "play": + petAction = PetAction.PLAY; + break; + case "sleep": + petAction = PetAction.SLEEP; + break; + default: + return BadRequest("Invalid action. Valid actions are: feed, play, sleep"); + } + + var actionRequest = new PetUpdateActionRequest { Action = petAction }; + var updatedPet = petService.UpdatePetAction(petId, userId.ToString(), actionRequest); + return Ok(updatedPet); + } + catch (Exception ex) + { + return NotFound(ex.Message); + } + } + + [HttpPut("{petId}/action/gather")] + public IActionResult UpdatePetActionGather(string petId, [FromBody] PetUpdateActionRequest actionRequest) { try { @@ -44,5 +86,39 @@ namespace pet_companion_api.Controllers return NotFound(ex.Message); } } + + [HttpGet("{petId}/resources/gathered")] + public IActionResult GetGatheredResources(string petId) + { + try + { + var resources = petService.GetGatheredResources(petId, userId.ToString()); + return Ok(resources); + } + catch (Exception ex) + { + return NotFound(ex.Message); + } + } + + [HttpPut("{petId}/resources/collect")] + public IActionResult CollectGatheredResources(string petId) + { + try + { + var updatedPet = petService.UpdatePetResources(petId, userId.ToString()); + return Ok(updatedPet); + } + catch (Exception ex) + { + return NotFound(ex.Message); + } + } + + [HttpGet("classes")] + public IActionResult GetAllPetClasses() + { + return Ok(petClassService.GetAllPetClasses()); + } } } diff --git a/Models/Pet.cs b/Models/Pet.cs index 7dcd9f6..679f935 100644 --- a/Models/Pet.cs +++ b/Models/Pet.cs @@ -13,7 +13,8 @@ namespace pet_companion_api.Models public int Level { get; set; } public string UserId { get; set; } public bool IsDead { get; set; } - public PetAction PetAction { get; set; } + + public PetActionGather PetAction { get; set; } public DateTime ActionSince { get; set; } } } diff --git a/Models/PetAction.cs b/Models/PetActionGather.cs similarity index 61% rename from Models/PetAction.cs rename to Models/PetActionGather.cs index 241f8f8..8b4aa3c 100644 --- a/Models/PetAction.cs +++ b/Models/PetActionGather.cs @@ -1,6 +1,14 @@ namespace pet_companion_api.Models { public enum PetAction + { + UNKNOWN, + FEED, + PLAY, + SLEEP, + } + + public enum PetActionGather { IDLE, GATHERING_WISDOM, diff --git a/Models/PetClassInfo.cs b/Models/PetClassInfo.cs index d21fa9c..1ecee2b 100644 --- a/Models/PetClassInfo.cs +++ b/Models/PetClassInfo.cs @@ -5,8 +5,25 @@ namespace pet_companion_api.Models { public string Name { get; set; } public string Description { get; set; } - public string[] Modifiers { get; set; } + public List Modifiers { get; set; } public string Color { get; set; } public string Emoji { get; set; } + public PetClass Class { get; set; } + } + + public class Modifier + { + public string Description { get; set; } + + /// + /// Other property (unused atm) + /// + public string? Misc { get; set; } + + /// + /// Either `intelligence`, `strength` or `charisma` + /// + public string? Attribute { get; set; } // The attribute that the modifier affects (used by reflection) + public float? Value { get; set; } } } \ No newline at end of file diff --git a/Models/PetUpdateActionRequest.cs b/Models/PetUpdateActionRequest.cs index c9c50a6..1c4be84 100644 --- a/Models/PetUpdateActionRequest.cs +++ b/Models/PetUpdateActionRequest.cs @@ -2,6 +2,7 @@ namespace pet_companion_api.Models { public class PetUpdateActionRequest { - public PetAction PetAction { get; set; } + public PetAction? Action { get; set; } + public PetActionGather? PetActionGather { get; set; } } } diff --git a/Program.cs b/Program.cs index 09045ad..4973c99 100644 --- a/Program.cs +++ b/Program.cs @@ -26,6 +26,8 @@ namespace pet_companion_api builder.Services.AddDbContext(options => options.UseSqlite(connectionString)); + builder.Services.AddScoped(); + builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); diff --git a/Repositories/PetClassRepository.cs b/Repositories/PetClassRepository.cs new file mode 100644 index 0000000..1838302 --- /dev/null +++ b/Repositories/PetClassRepository.cs @@ -0,0 +1,121 @@ +using Microsoft.EntityFrameworkCore; +using pet_companion_api.Data; +using pet_companion_api.Models; + +namespace pet_companion_api.Repositories +{ + public class PetClassRepository + { + private readonly ApplicationDbContext _context; + + public PetClassRepository(ApplicationDbContext context) + { + _context = context; + } + + public IEnumerable GetAllPetClassesInfo() + { + return new List + { + new PetClassInfo + { + Name = "Forest Spirit", + Description = "A mystical guardian of nature, attuned to the forest's wisdom.", + Modifiers = new List + { + new Modifier { Description = "-20% food consumption" }, + new Modifier { Description = "+15% wisdom generation" }, + new Modifier { Description = "Natural healing ability" } + }, + Color = "emerald", + Emoji = "🌿", + Class = PetClass.FOREST_SPIRIT + }, + new PetClassInfo + { + Name = "Ocean Guardian", + Description = "A majestic creature of the deep, master of the seas.", + Modifiers = new List + { + new Modifier { Description = "+20% resource gathering" }, + new Modifier { Description = "Water breathing" }, + new Modifier { Description = "Enhanced mobility" } + }, + Color = "cyan", + Emoji = "🌊", + Class = PetClass.OCEAN_GUARDIAN + }, + new PetClassInfo + { + Name = "Fire Elemental", + Description = "A passionate spirit of flame, burning with inner strength.", + Modifiers = new List + { + new Modifier { Description = "+25% strength gains" }, + new Modifier { Description = "Fire resistance" }, + new Modifier { Description = "Heat generation" } + }, + Color = "red", + Emoji = "🔥", + Class = PetClass.FIRE_ELEMENTAL + }, + new PetClassInfo + { + Name = "Mythical Beast", + Description = "A legendary creature of ancient lore.", + Modifiers = new List + { + new Modifier { Description = "+30% charisma" }, + new Modifier { Description = "Rare item finding" }, + new Modifier { Description = "Enhanced abilities at night" } + }, + Color = "purple", + Emoji = "🦄", + Class = PetClass.MYTHICAL_BEAST + }, + new PetClassInfo + { + Name = "Shadow Walker", + Description = "A mysterious being that moves between light and darkness.", + Modifiers = new List + { + new Modifier { Description = "Stealth abilities" }, + new Modifier { Description = "+25% junk value" }, + new Modifier { Description = "Night vision" } + }, + Color = "violet", + Emoji = "👻", + Class = PetClass.SHADOW_WALKER + }, + new PetClassInfo + { + Name = "Cyber Pet", + Description = "A digital companion from the future.", + Modifiers = new List + { + new Modifier { Description = "+30% intelligence growth" }, + new Modifier { Description = "Digital interface" }, + new Modifier { Description = "Quick processing" } + }, + Color = "blue", + Emoji = "🤖", + Class = PetClass.CYBER_PET + }, + new PetClassInfo + { + Name = "Bio-Mechanical Hybrid", + Description = "A perfect fusion of organic life and advanced technology.", + Modifiers = new List + { + new Modifier { Description = "Self-repair capability" }, + new Modifier { Description = "+20% all stats" }, + new Modifier { Description = "Resource optimization" } + }, + Color = "teal", + Emoji = "🦾", + Class = PetClass.BIO_MECHANICAL + } + }; + } + } +} diff --git a/Repositories/PetRepository.cs b/Repositories/PetRepository.cs index 11f5de2..6ef0c31 100644 --- a/Repositories/PetRepository.cs +++ b/Repositories/PetRepository.cs @@ -6,16 +6,16 @@ namespace pet_companion_api.Repositories { public class PetRepository { - private readonly ApplicationDbContext _context; + private readonly ApplicationDbContext context; public PetRepository(ApplicationDbContext context) { - _context = context; + this.context = context; } public IEnumerable GetPetsByUserId(string userId) { - return _context.Pets + return context.Pets .Where(p => p.UserId == userId) .Include(p => p.Stats) .Include(p => p.Resources) @@ -24,30 +24,42 @@ namespace pet_companion_api.Repositories public Pet GetPetById(string petId, string userId) { - return _context.Pets - .FirstOrDefault(p => p.Id == petId && p.UserId == userId); + return context.Pets + .Where(p => p.Id == petId && p.UserId == userId) + .Include(p => p.Stats) + .Include(p => p.Resources) + .FirstOrDefault(); } public Pet CreatePet(Pet pet) { - _context.Pets.Add(pet); - _context.SaveChanges(); + context.Pets.Add(pet); + context.SaveChanges(); return pet; } public Pet UpdatePet(Pet pet) { - _context.Pets.Update(pet); - _context.SaveChanges(); + context.Pets.Update(pet); + context.SaveChanges(); return pet; } public Pet UpdatePetAction(Pet pet) { - _context.Pets.Attach(pet); - _context.Entry(pet).Property(p => p.PetAction).IsModified = true; - _context.Entry(pet).Property(p => p.ActionSince).IsModified = true; - _context.SaveChanges(); + context.Pets.Attach(pet); + context.Entry(pet).Property(p => p.PetAction).IsModified = true; + context.Entry(pet).Property(p => p.ActionSince).IsModified = true; + context.SaveChanges(); + return pet; + } + + public Pet UpdatePetResources(Pet pet) + { + context.Pets.Attach(pet); + context.Entry(pet).Reference(p => p.Resources).IsModified = true; + context.Entry(pet).Property(p => p.ActionSince).IsModified = true; + context.SaveChanges(); return pet; } } diff --git a/Services/PetClassService.cs b/Services/PetClassService.cs new file mode 100644 index 0000000..dd45030 --- /dev/null +++ b/Services/PetClassService.cs @@ -0,0 +1,47 @@ +using pet_companion_api.Models; +using pet_companion_api.Repositories; + +namespace pet_companion_api.Services +{ + public class PetClassService + { + private readonly PetClassRepository _petClassRepository; + + public PetClassService(PetClassRepository petClassRepository) + { + _petClassRepository = petClassRepository; + } + + public IEnumerable GetAllPetClasses() + { + return _petClassRepository.GetAllPetClassesInfo(); + } + + public Resources CalculateGatheredResources(PetStats stats, int petLevel, PetActionGather action, DateTime actionSince) + { + var timeElapsed = (DateTime.UtcNow - actionSince).TotalHours; + var resources = new Resources(); + + if (action == PetActionGather.IDLE) + return resources; + + var baseRate = timeElapsed * 0.5 + petLevel; // Base rate per hour + resources.Junk = (int)(baseRate * 2); + + switch (action) + { + case PetActionGather.GATHERING_WISDOM: + resources.Wisdom = (int)(baseRate * (stats.Intelligence * 2)); + break; + case PetActionGather.GATHERING_GOLD: + resources.Gold = (int)(baseRate * (stats.Charisma * 2)); + break; + case PetActionGather.GATHERING_FOOD: + resources.Food = (int)(baseRate * (stats.Strength * 1.5)); + break; + } + + return resources; + } + } +} diff --git a/Services/PetService.cs b/Services/PetService.cs index 25a7461..1804b8b 100644 --- a/Services/PetService.cs +++ b/Services/PetService.cs @@ -6,10 +6,12 @@ namespace pet_companion_api.Services public class PetService { private readonly PetRepository petRepository; + private readonly PetClassService _petClassService; - public PetService(PetRepository petRepository) + public PetService(PetRepository petRepository, PetClassService petClassService) { this.petRepository = petRepository; + _petClassService = petClassService; } public IEnumerable GetAllPets(Guid userId) @@ -29,7 +31,7 @@ namespace pet_companion_api.Services Stats = PetStats.BuildFromClass(petRequest.Class), Resources = new Resources(), ActionSince = DateTime.UtcNow, - PetAction = PetAction.IDLE, + PetAction = PetActionGather.IDLE, IsDead = false }; @@ -44,10 +46,50 @@ namespace pet_companion_api.Services throw new Exception("Pet not found"); } - pet.PetAction = actionRequest.PetAction; + if (actionRequest.Action.HasValue) + { + // not implemented + } + else if (actionRequest.PetActionGather.HasValue) + { + pet.PetAction = actionRequest.PetActionGather.Value; + pet.ActionSince = DateTime.UtcNow; + + return petRepository.UpdatePetAction(pet); + } + + return pet; + } + + public Resources GetGatheredResources(string petId, string userId) + { + var pet = petRepository.GetPetById(petId, userId); + + if (pet == null) + { + throw new Exception("Pet not found"); + } + + return _petClassService.CalculateGatheredResources(pet.Stats, pet.Level, pet.PetAction, pet.ActionSince); + } + + public Pet UpdatePetResources(string petId, string userId) + { + var pet = petRepository.GetPetById(petId, userId); + if (pet == null) + { + throw new Exception("Pet not found"); + } + + var gatheredResources = _petClassService.CalculateGatheredResources(pet.Stats, pet.Level, pet.PetAction, pet.ActionSince); + + pet.Resources.Wisdom += gatheredResources.Wisdom; + pet.Resources.Gold += gatheredResources.Gold; + pet.Resources.Food += gatheredResources.Food; + pet.Resources.Junk += gatheredResources.Junk; pet.ActionSince = DateTime.UtcNow; - return petRepository.UpdatePetAction(pet); + return petRepository.UpdatePetResources(pet); } } } diff --git a/pet-companion-api.http b/pet-companion-api.http deleted file mode 100644 index be3ce9b..0000000 --- a/pet-companion-api.http +++ /dev/null @@ -1,6 +0,0 @@ -@pet_companion_api_HostAddress = http://localhost:5278 - -GET {{pet_companion_api_HostAddress}}/weatherforecast/ -Accept: application/json - -###