Add pet action management and update requests

This commit is contained in:
Jose Henrique 2025-02-01 00:29:33 -03:00
parent 4c4036a266
commit e1c5eed02d
12 changed files with 337 additions and 36 deletions

View File

@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using pet_companion_api.Models;
using pet_companion_api.Services; using pet_companion_api.Services;
namespace pet_companion_api.Controllers namespace pet_companion_api.Controllers
@ -22,5 +23,26 @@ namespace pet_companion_api.Controllers
{ {
return Ok(petService.GetAllPets(userId)); 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);
}
}
} }
} }

View File

@ -0,0 +1,126 @@
// <auto-generated />
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
{
/// <inheritdoc />
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<string>("Id")
.HasColumnType("TEXT");
b.Property<DateTime>("ActionSince")
.HasColumnType("TEXT");
b.Property<int>("Class")
.HasColumnType("INTEGER");
b.Property<bool>("IsDead")
.HasColumnType("INTEGER");
b.Property<int>("Level")
.HasColumnType("INTEGER");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("PetAction")
.HasColumnType("INTEGER");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("Pets");
});
modelBuilder.Entity("pet_companion_api.Models.PetStats", b =>
{
b.Property<string>("PetId")
.HasColumnType("TEXT");
b.Property<int>("Charisma")
.HasColumnType("INTEGER");
b.Property<int>("Intelligence")
.HasColumnType("INTEGER");
b.Property<int>("Strength")
.HasColumnType("INTEGER");
b.HasKey("PetId");
b.ToTable("PetStats");
});
modelBuilder.Entity("pet_companion_api.Models.Resources", b =>
{
b.Property<string>("PetId")
.HasColumnType("TEXT");
b.Property<int>("Food")
.HasColumnType("INTEGER");
b.Property<int>("Gold")
.HasColumnType("INTEGER");
b.Property<int>("Junk")
.HasColumnType("INTEGER");
b.Property<int>("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
}
}
}

View File

@ -0,0 +1,52 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace pet_companion_api.Migrations
{
/// <inheritdoc />
public partial class AddActions : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<DateTime>(
name: "ActionSince",
table: "Pets",
type: "TEXT",
nullable: false,
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
migrationBuilder.AddColumn<bool>(
name: "IsDead",
table: "Pets",
type: "INTEGER",
nullable: false,
defaultValue: false);
migrationBuilder.AddColumn<int>(
name: "PetAction",
table: "Pets",
type: "INTEGER",
nullable: false,
defaultValue: 0);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "ActionSince",
table: "Pets");
migrationBuilder.DropColumn(
name: "IsDead",
table: "Pets");
migrationBuilder.DropColumn(
name: "PetAction",
table: "Pets");
}
}
}

View File

@ -1,4 +1,5 @@
// <auto-generated /> // <auto-generated />
using System;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
@ -21,9 +22,15 @@ namespace pet_companion_api.Migrations
b.Property<string>("Id") b.Property<string>("Id")
.HasColumnType("TEXT"); .HasColumnType("TEXT");
b.Property<DateTime>("ActionSince")
.HasColumnType("TEXT");
b.Property<int>("Class") b.Property<int>("Class")
.HasColumnType("INTEGER"); .HasColumnType("INTEGER");
b.Property<bool>("IsDead")
.HasColumnType("INTEGER");
b.Property<int>("Level") b.Property<int>("Level")
.HasColumnType("INTEGER"); .HasColumnType("INTEGER");
@ -31,6 +38,9 @@ namespace pet_companion_api.Migrations
.IsRequired() .IsRequired()
.HasColumnType("TEXT"); .HasColumnType("TEXT");
b.Property<int>("PetAction")
.HasColumnType("INTEGER");
b.Property<string>("UserId") b.Property<string>("UserId")
.IsRequired() .IsRequired()
.HasColumnType("TEXT"); .HasColumnType("TEXT");

View File

@ -12,5 +12,8 @@ namespace pet_companion_api.Models
public Resources Resources { get; set; } public Resources Resources { get; set; }
public int Level { get; set; } public int Level { get; set; }
public string UserId { get; set; } public string UserId { get; set; }
public bool IsDead { get; set; }
public PetAction PetAction { get; set; }
public DateTime ActionSince { get; set; }
} }
} }

10
Models/PetAction.cs Normal file
View File

@ -0,0 +1,10 @@
namespace pet_companion_api.Models
{
public enum PetAction
{
IDLE,
GATHERING_WISDOM,
GATHERING_GOLD,
GATHERING_FOOD,
}
}

View File

@ -0,0 +1,8 @@
namespace pet_companion_api.Models
{
public class PetCreationRequest
{
public string Name { get; set; }
public PetClass Class { get; set; }
}
}

View File

@ -11,56 +11,55 @@ namespace pet_companion_api.Models
public int Strength { get; set; } public int Strength { get; set; }
public int Charisma { 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) switch (petClass)
{ {
case PetClass.FOREST_SPIRIT: case PetClass.FOREST_SPIRIT:
Intelligence = 10; stats.Intelligence = 10;
Strength = 5; stats.Strength = 5;
Charisma = 5; stats.Charisma = 5;
break; break;
case PetClass.OCEAN_GUARDIAN: case PetClass.OCEAN_GUARDIAN:
Intelligence = 5; stats.Intelligence = 5;
Strength = 10; stats.Strength = 10;
Charisma = 5; stats.Charisma = 5;
break; break;
case PetClass.FIRE_ELEMENTAL: case PetClass.FIRE_ELEMENTAL:
Intelligence = 5; stats.Intelligence = 5;
Strength = 5; stats.Strength = 5;
Charisma = 10; stats.Charisma = 10;
break; break;
case PetClass.MYTHICAL_BEAST: case PetClass.MYTHICAL_BEAST:
Intelligence = 7; stats.Intelligence = 7;
Strength = 7; stats.Strength = 7;
Charisma = 7; stats.Charisma = 7;
break; break;
case PetClass.SHADOW_WALKER: case PetClass.SHADOW_WALKER:
Intelligence = 8; stats.Intelligence = 8;
Strength = 6; stats.Strength = 6;
Charisma = 6; stats.Charisma = 6;
break; break;
case PetClass.CYBER_PET: case PetClass.CYBER_PET:
Intelligence = 8; stats.Intelligence = 8;
Strength = 8; stats.Strength = 8;
Charisma = 6; stats.Charisma = 6;
break; break;
case PetClass.BIO_MECHANICAL: case PetClass.BIO_MECHANICAL:
Intelligence = 8; stats.Intelligence = 8;
Strength = 6; stats.Strength = 6;
Charisma = 8; stats.Charisma = 8;
break; break;
default: default:
Intelligence = 5; stats.Intelligence = 5;
Strength = 5; stats.Strength = 5;
Charisma = 5; stats.Charisma = 5;
break; break;
} }
return stats;
} }
} }
} }

View File

@ -0,0 +1,7 @@
namespace pet_companion_api.Models
{
public class PetUpdateActionRequest
{
public PetAction PetAction { get; set; }
}
}

View File

@ -2,6 +2,7 @@ using Microsoft.EntityFrameworkCore;
using pet_companion_api.Data; using pet_companion_api.Data;
using pet_companion_api.Repositories; using pet_companion_api.Repositories;
using pet_companion_api.Services; using pet_companion_api.Services;
using System.Text.Json.Serialization;
namespace pet_companion_api namespace pet_companion_api
{ {
@ -12,7 +13,11 @@ namespace pet_companion_api
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
// Add services to the container. // Add services to the container.
builder.Services.AddControllers(); builder.Services.AddControllers()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
});
builder.Services.AddEndpointsApiExplorer(); builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(); builder.Services.AddSwaggerGen();
@ -24,6 +29,17 @@ namespace pet_companion_api
builder.Services.AddScoped<PetRepository>(); builder.Services.AddScoped<PetRepository>();
builder.Services.AddScoped<PetService>(); builder.Services.AddScoped<PetService>();
// Add CORS policy
builder.Services.AddCors(options =>
{
options.AddPolicy("AllowAll", builder =>
{
builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
});
});
var app = builder.Build(); var app = builder.Build();
// Configure the HTTP request pipeline. // Configure the HTTP request pipeline.
@ -35,6 +51,10 @@ namespace pet_companion_api
app.UseHttpsRedirection(); app.UseHttpsRedirection();
app.UseAuthorization(); app.UseAuthorization();
// Use CORS policy
app.UseCors("AllowAll");
app.MapControllers(); app.MapControllers();
app.Run(); app.Run();
} }

View File

@ -22,11 +22,33 @@ namespace pet_companion_api.Repositories
.ToList(); .ToList();
} }
public Pet GetPetById(string petId, string userId)
{
return _context.Pets
.FirstOrDefault(p => p.Id == petId && p.UserId == userId);
}
public Pet CreatePet(Pet pet) public Pet CreatePet(Pet pet)
{ {
_context.Pets.Add(pet); _context.Pets.Add(pet);
_context.SaveChanges(); _context.SaveChanges();
return pet; 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;
}
} }
} }

View File

@ -17,15 +17,37 @@ namespace pet_companion_api.Services
return petRepository.GetPetsByUserId(userId.ToString()); return petRepository.GetPetsByUserId(userId.ToString());
} }
public Pet CreatePet(Guid userId, Pet pet) public Pet CreatePet(Guid userId, PetCreationRequest petRequest)
{ {
pet.Id = Guid.NewGuid().ToString(); var pet = new Pet
pet.UserId = userId.ToString(); {
pet.Level = 1; Id = Guid.NewGuid().ToString(),
pet.Stats = new PetStats(pet.Class); UserId = userId.ToString(),
pet.Resources = new Resources(); 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); 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);
}
} }
} }