From e1c5eed02d8a617c7a0a986acf357b02b8c57108 Mon Sep 17 00:00:00 2001 From: Jose Henrique Date: Sat, 1 Feb 2025 00:29:33 -0300 Subject: [PATCH] Add pet action management and update requests --- Controllers/PetController.cs | 22 +++ .../20250201025206_AddActions.Designer.cs | 126 ++++++++++++++++++ Migrations/20250201025206_AddActions.cs | 52 ++++++++ .../ApplicationDbContextModelSnapshot.cs | 10 ++ Models/Pet.cs | 3 + Models/PetAction.cs | 10 ++ Models/PetCreationRequest.cs | 8 ++ Models/PetStats.cs | 57 ++++---- Models/PetUpdateActionRequest.cs | 7 + Program.cs | 22 ++- Repositories/PetRepository.cs | 22 +++ Services/PetService.cs | 34 ++++- 12 files changed, 337 insertions(+), 36 deletions(-) create mode 100644 Migrations/20250201025206_AddActions.Designer.cs create mode 100644 Migrations/20250201025206_AddActions.cs create mode 100644 Models/PetAction.cs create mode 100644 Models/PetCreationRequest.cs create mode 100644 Models/PetUpdateActionRequest.cs diff --git a/Controllers/PetController.cs b/Controllers/PetController.cs index 7659e8a..2c921c2 100644 --- a/Controllers/PetController.cs +++ b/Controllers/PetController.cs @@ -1,4 +1,5 @@ using Microsoft.AspNetCore.Mvc; +using pet_companion_api.Models; using pet_companion_api.Services; namespace pet_companion_api.Controllers @@ -22,5 +23,26 @@ namespace pet_companion_api.Controllers { return Ok(petService.GetAllPets(userId)); } + + [HttpPost("")] + public IActionResult CreatePet([FromBody] PetCreationRequest petRequest) + { + var createdPet = petService.CreatePet(userId, petRequest); + return CreatedAtAction(nameof(GetAllPets), new { id = createdPet.Id }, createdPet); + } + + [HttpPut("{petId}/action")] + public IActionResult UpdatePetAction(string petId, [FromBody] PetUpdateActionRequest actionRequest) + { + try + { + var updatedPet = petService.UpdatePetAction(petId, userId.ToString(), actionRequest); + return Ok(updatedPet); + } + catch (Exception ex) + { + return NotFound(ex.Message); + } + } } } diff --git a/Migrations/20250201025206_AddActions.Designer.cs b/Migrations/20250201025206_AddActions.Designer.cs new file mode 100644 index 0000000..05664b0 --- /dev/null +++ b/Migrations/20250201025206_AddActions.Designer.cs @@ -0,0 +1,126 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using pet_companion_api.Data; + +#nullable disable + +namespace pet_companion_api.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20250201025206_AddActions")] + partial class AddActions + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "9.0.1"); + + modelBuilder.Entity("pet_companion_api.Models.Pet", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ActionSince") + .HasColumnType("TEXT"); + + b.Property("Class") + .HasColumnType("INTEGER"); + + b.Property("IsDead") + .HasColumnType("INTEGER"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("PetAction") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Pets"); + }); + + modelBuilder.Entity("pet_companion_api.Models.PetStats", b => + { + b.Property("PetId") + .HasColumnType("TEXT"); + + b.Property("Charisma") + .HasColumnType("INTEGER"); + + b.Property("Intelligence") + .HasColumnType("INTEGER"); + + b.Property("Strength") + .HasColumnType("INTEGER"); + + b.HasKey("PetId"); + + b.ToTable("PetStats"); + }); + + modelBuilder.Entity("pet_companion_api.Models.Resources", b => + { + b.Property("PetId") + .HasColumnType("TEXT"); + + b.Property("Food") + .HasColumnType("INTEGER"); + + b.Property("Gold") + .HasColumnType("INTEGER"); + + b.Property("Junk") + .HasColumnType("INTEGER"); + + b.Property("Wisdom") + .HasColumnType("INTEGER"); + + b.HasKey("PetId"); + + b.ToTable("Resources"); + }); + + modelBuilder.Entity("pet_companion_api.Models.PetStats", b => + { + b.HasOne("pet_companion_api.Models.Pet", null) + .WithOne("Stats") + .HasForeignKey("pet_companion_api.Models.PetStats", "PetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("pet_companion_api.Models.Resources", b => + { + b.HasOne("pet_companion_api.Models.Pet", null) + .WithOne("Resources") + .HasForeignKey("pet_companion_api.Models.Resources", "PetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("pet_companion_api.Models.Pet", b => + { + b.Navigation("Resources") + .IsRequired(); + + b.Navigation("Stats") + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Migrations/20250201025206_AddActions.cs b/Migrations/20250201025206_AddActions.cs new file mode 100644 index 0000000..6e7717b --- /dev/null +++ b/Migrations/20250201025206_AddActions.cs @@ -0,0 +1,52 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace pet_companion_api.Migrations +{ + /// + public partial class AddActions : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "ActionSince", + table: "Pets", + type: "TEXT", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); + + migrationBuilder.AddColumn( + name: "IsDead", + table: "Pets", + type: "INTEGER", + nullable: false, + defaultValue: false); + + migrationBuilder.AddColumn( + name: "PetAction", + table: "Pets", + type: "INTEGER", + nullable: false, + defaultValue: 0); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "ActionSince", + table: "Pets"); + + migrationBuilder.DropColumn( + name: "IsDead", + table: "Pets"); + + migrationBuilder.DropColumn( + name: "PetAction", + table: "Pets"); + } + } +} diff --git a/Migrations/ApplicationDbContextModelSnapshot.cs b/Migrations/ApplicationDbContextModelSnapshot.cs index 2201878..99dae93 100644 --- a/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/Migrations/ApplicationDbContextModelSnapshot.cs @@ -1,4 +1,5 @@ // +using System; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; @@ -21,9 +22,15 @@ namespace pet_companion_api.Migrations b.Property("Id") .HasColumnType("TEXT"); + b.Property("ActionSince") + .HasColumnType("TEXT"); + b.Property("Class") .HasColumnType("INTEGER"); + b.Property("IsDead") + .HasColumnType("INTEGER"); + b.Property("Level") .HasColumnType("INTEGER"); @@ -31,6 +38,9 @@ namespace pet_companion_api.Migrations .IsRequired() .HasColumnType("TEXT"); + b.Property("PetAction") + .HasColumnType("INTEGER"); + b.Property("UserId") .IsRequired() .HasColumnType("TEXT"); diff --git a/Models/Pet.cs b/Models/Pet.cs index 4a25790..7dcd9f6 100644 --- a/Models/Pet.cs +++ b/Models/Pet.cs @@ -12,5 +12,8 @@ namespace pet_companion_api.Models public Resources Resources { get; set; } public int Level { get; set; } public string UserId { get; set; } + public bool IsDead { get; set; } + public PetAction PetAction { get; set; } + public DateTime ActionSince { get; set; } } } diff --git a/Models/PetAction.cs b/Models/PetAction.cs new file mode 100644 index 0000000..241f8f8 --- /dev/null +++ b/Models/PetAction.cs @@ -0,0 +1,10 @@ +namespace pet_companion_api.Models +{ + public enum PetAction + { + IDLE, + GATHERING_WISDOM, + GATHERING_GOLD, + GATHERING_FOOD, + } +} \ No newline at end of file diff --git a/Models/PetCreationRequest.cs b/Models/PetCreationRequest.cs new file mode 100644 index 0000000..5f7d3e5 --- /dev/null +++ b/Models/PetCreationRequest.cs @@ -0,0 +1,8 @@ +namespace pet_companion_api.Models +{ + public class PetCreationRequest + { + public string Name { get; set; } + public PetClass Class { get; set; } + } +} diff --git a/Models/PetStats.cs b/Models/PetStats.cs index a5ea3e5..cd48302 100644 --- a/Models/PetStats.cs +++ b/Models/PetStats.cs @@ -11,56 +11,55 @@ namespace pet_companion_api.Models public int Strength { get; set; } public int Charisma { get; set; } - public PetStats(PetClass petClass) + public static PetStats BuildFromClass(PetClass petClass) { - BuildFromClass(petClass); - } + var stats = new PetStats(); - public void BuildFromClass(PetClass petClass) - { switch (petClass) { case PetClass.FOREST_SPIRIT: - Intelligence = 10; - Strength = 5; - Charisma = 5; + stats.Intelligence = 10; + stats.Strength = 5; + stats.Charisma = 5; break; case PetClass.OCEAN_GUARDIAN: - Intelligence = 5; - Strength = 10; - Charisma = 5; + stats.Intelligence = 5; + stats.Strength = 10; + stats.Charisma = 5; break; case PetClass.FIRE_ELEMENTAL: - Intelligence = 5; - Strength = 5; - Charisma = 10; + stats.Intelligence = 5; + stats.Strength = 5; + stats.Charisma = 10; break; case PetClass.MYTHICAL_BEAST: - Intelligence = 7; - Strength = 7; - Charisma = 7; + stats.Intelligence = 7; + stats.Strength = 7; + stats.Charisma = 7; break; case PetClass.SHADOW_WALKER: - Intelligence = 8; - Strength = 6; - Charisma = 6; + stats.Intelligence = 8; + stats.Strength = 6; + stats.Charisma = 6; break; case PetClass.CYBER_PET: - Intelligence = 8; - Strength = 8; - Charisma = 6; + stats.Intelligence = 8; + stats.Strength = 8; + stats.Charisma = 6; break; case PetClass.BIO_MECHANICAL: - Intelligence = 8; - Strength = 6; - Charisma = 8; + stats.Intelligence = 8; + stats.Strength = 6; + stats.Charisma = 8; break; default: - Intelligence = 5; - Strength = 5; - Charisma = 5; + stats.Intelligence = 5; + stats.Strength = 5; + stats.Charisma = 5; break; } + + return stats; } } } diff --git a/Models/PetUpdateActionRequest.cs b/Models/PetUpdateActionRequest.cs new file mode 100644 index 0000000..c9c50a6 --- /dev/null +++ b/Models/PetUpdateActionRequest.cs @@ -0,0 +1,7 @@ +namespace pet_companion_api.Models +{ + public class PetUpdateActionRequest + { + public PetAction PetAction { get; set; } + } +} diff --git a/Program.cs b/Program.cs index 7680336..09045ad 100644 --- a/Program.cs +++ b/Program.cs @@ -2,6 +2,7 @@ using Microsoft.EntityFrameworkCore; using pet_companion_api.Data; using pet_companion_api.Repositories; using pet_companion_api.Services; +using System.Text.Json.Serialization; namespace pet_companion_api { @@ -12,7 +13,11 @@ namespace pet_companion_api var builder = WebApplication.CreateBuilder(args); // Add services to the container. - builder.Services.AddControllers(); + builder.Services.AddControllers() + .AddJsonOptions(options => + { + options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); + }); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); @@ -24,6 +29,17 @@ namespace pet_companion_api builder.Services.AddScoped(); builder.Services.AddScoped(); + // Add CORS policy + builder.Services.AddCors(options => + { + options.AddPolicy("AllowAll", builder => + { + builder.AllowAnyOrigin() + .AllowAnyMethod() + .AllowAnyHeader(); + }); + }); + var app = builder.Build(); // Configure the HTTP request pipeline. @@ -35,6 +51,10 @@ namespace pet_companion_api app.UseHttpsRedirection(); app.UseAuthorization(); + + // Use CORS policy + app.UseCors("AllowAll"); + app.MapControllers(); app.Run(); } diff --git a/Repositories/PetRepository.cs b/Repositories/PetRepository.cs index ab54ad1..11f5de2 100644 --- a/Repositories/PetRepository.cs +++ b/Repositories/PetRepository.cs @@ -22,11 +22,33 @@ namespace pet_companion_api.Repositories .ToList(); } + public Pet GetPetById(string petId, string userId) + { + return _context.Pets + .FirstOrDefault(p => p.Id == petId && p.UserId == userId); + } + public Pet CreatePet(Pet pet) { _context.Pets.Add(pet); _context.SaveChanges(); return pet; } + + public Pet UpdatePet(Pet pet) + { + _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(); + return pet; + } } } diff --git a/Services/PetService.cs b/Services/PetService.cs index a6cb11b..25a7461 100644 --- a/Services/PetService.cs +++ b/Services/PetService.cs @@ -17,15 +17,37 @@ namespace pet_companion_api.Services return petRepository.GetPetsByUserId(userId.ToString()); } - public Pet CreatePet(Guid userId, Pet pet) + public Pet CreatePet(Guid userId, PetCreationRequest petRequest) { - pet.Id = Guid.NewGuid().ToString(); - pet.UserId = userId.ToString(); - pet.Level = 1; - pet.Stats = new PetStats(pet.Class); - pet.Resources = new Resources(); + var pet = new Pet + { + Id = Guid.NewGuid().ToString(), + UserId = userId.ToString(), + Name = petRequest.Name, + Class = petRequest.Class, + Level = 1, + Stats = PetStats.BuildFromClass(petRequest.Class), + Resources = new Resources(), + ActionSince = DateTime.UtcNow, + PetAction = PetAction.IDLE, + IsDead = false + }; return petRepository.CreatePet(pet); } + + public Pet UpdatePetAction(string petId, string userId, PetUpdateActionRequest actionRequest) + { + var pet = petRepository.GetPetById(petId, userId); + if (pet == null) + { + throw new Exception("Pet not found"); + } + + pet.PetAction = actionRequest.PetAction; + pet.ActionSince = DateTime.UtcNow; + + return petRepository.UpdatePetAction(pet); + } } }