Skip to content

Commit

Permalink
Add migration with database correction
Browse files Browse the repository at this point in the history
  • Loading branch information
MarcinKanarDev committed Feb 1, 2025
1 parent d1ef62b commit dfde8fa
Show file tree
Hide file tree
Showing 15 changed files with 588 additions and 27 deletions.
9 changes: 7 additions & 2 deletions server/src/Questeloper.Application/Hero/Queries/Extensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
namespace Questeloper.Application.Hero.Queries;
using Questeloper.Domain.Entities;

namespace Questeloper.Application.Hero.Queries;

internal static class Extensions
{
Expand All @@ -9,5 +11,8 @@ public static GetHeroResponse ToResponse(this Domain.Entities.Hero hero) =>
hero.HeroClass.ClassName.Value,
hero.Experience.ExperiencePoints,
hero.HealthPoints.Points,
hero.ManaPoints.Points);
hero.ManaPoints.Points);

public static GetHeroClassesResponse ToResponse(this HeroClass heroClass) =>
new GetHeroClassesResponse(heroClass.ClassName.Value);
}
4 changes: 3 additions & 1 deletion server/src/Questeloper.Domain/Entities/Hero.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ public class Hero : EntityBase
{
public HeroName HeroName { get; private set; }
public Level Level { get; private set; }
public HeroClass HeroClass { get; private set; }
public Experience Experience { get; private set; }
public HealthPoints HealthPoints { get; private set; }
public ManaPoints ManaPoints { get; private set; }

// Relations
public int HeroClassId { get; set; }
public HeroClass HeroClass { get; private set; }
public ICollection<Battle> Battles { get; set; }

public Hero()
Expand Down
7 changes: 7 additions & 0 deletions server/src/Questeloper.Domain/Entities/HeroClass.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ namespace Questeloper.Domain.Entities;
public class HeroClass : EntityBase
{
public HeroClassName ClassName { get; private set; }

// Relations
public ICollection<Hero> Heroes { get; set; }

public HeroClass()
{
}

public HeroClass(string className)
{
Expand Down
3 changes: 2 additions & 1 deletion server/src/Questeloper.Domain/Entities/Question.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ namespace Questeloper.Domain.Entities;
public abstract class Question : EntityBase
{
public QuestionContent? Content { get; set; }


// Relations
public int EnemyId { get; set; }
public Enemy Enemy { get; set; }
public ICollection<Category> Categories { get; set; }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,30 @@
using Microsoft.EntityFrameworkCore;
using MediatR;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Questeloper.Domain.Abstractions;

namespace Questeloper.Infrastructure.Persistence.DatabaseSeeders;

internal sealed class DatabaseInitializer(IServiceProvider serviceProvider, IClock clock) : IHostedService
internal sealed class DatabaseInitializer(IServiceProvider serviceProvider, IClock clock,
ILogger<DatabaseInitializer> logger, ILoggerFactory loggerFactory) : IHostedService
{
public async Task StartAsync(CancellationToken cancellationToken)
{
logger.LogInformation("Starting database initializer...");

using var scope = serviceProvider.CreateScope();

var dbContext = scope.ServiceProvider.GetRequiredService<QuesteloperDbContext>();
await dbContext.Database.MigrateAsync(cancellationToken);

var heroSeeder = new QuesteloperDataSeeder(dbContext, clock);
var heroSeeder = new QuesteloperDataSeeder(dbContext, loggerFactory.CreateLogger<QuesteloperDataSeeder>(), clock);
await heroSeeder.SeedAsync();

await dbContext.SaveChangesAsync(cancellationToken);

logger.LogInformation("Database initialisation was succesfull!");
}

public async Task StopAsync(CancellationToken cancellationToken) => await Task.CompletedTask;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
using Bogus;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Questeloper.Domain.Abstractions;
using Questeloper.Domain.Entities;
using Questeloper.Domain.ValueObjects;

namespace Questeloper.Infrastructure.Persistence.DatabaseSeeders;

internal sealed class QuesteloperDataSeeder(QuesteloperDbContext questeloperDbContext, IClock clock)
internal sealed class QuesteloperDataSeeder(QuesteloperDbContext questeloperDbContext, ILogger<QuesteloperDataSeeder> logger, IClock clock)
{
private readonly string[] HeroClasses = { "Front-End Developer", "Back-End Developer", "Tester" };

internal async Task SeedAsync()
internal async Task SeedAsync()
{
if (!questeloperDbContext.HeroClasses.Any()) await GenerateHeroClasses();
if (!questeloperDbContext.Heroes.Any()) await GenerateHeroes();
Expand All @@ -20,44 +21,70 @@ internal async Task SeedAsync()
if (!questeloperDbContext.Users.Any()) await GenerateUsers();
}

#region Generators

private async Task GenerateHeroClasses()
{
var heroeClassesFaker = new Faker<HeroClass>()
.RuleFor(x => x.ClassName, x =>
new HeroClassName(x.PickRandom(HeroClasses)));
logger.LogInformation("Generating hero classes...");

var heroClassesToSeed = new List<HeroClass>();

foreach (var className in HeroClasses)
{
var heroeClassesFaker = new Faker<HeroClass>()
.RuleFor(x => x.ClassName, x => new HeroClassName(className));

heroClassesToSeed.Add(heroeClassesFaker);
}

var heroClassesToSeed = heroeClassesFaker.Generate(2);
await questeloperDbContext.HeroClasses.AddRangeAsync(heroClassesToSeed);
await questeloperDbContext.SaveChangesAsync();

logger.LogInformation("Generating hero classes succesful!");
}

private async Task GenerateHeroes()
{
{
logger.LogInformation("Generating heroes...");

var heroClassIds = await questeloperDbContext.HeroClasses.Select(x => x.Id).ToListAsync();

var heroesFaker = new Faker<Hero>()
.RuleFor(x => x.Level, x => new Level(x.Random.Int(1, 100)))
.RuleFor(x => x.HeroName, x => new HeroName(x.Person.UserName))
.RuleFor(x => x.Experience, x => new Experience(x.Random.Int(1, 10000)))
.RuleFor(x => x.HealthPoints, x => new HealthPoints(x.Random.Int(1, 100)))
.RuleFor(x => x.ManaPoints, x => new ManaPoints(x.Random.Int(1, 100)))
.RuleFor(x => x.HeroClassId, x => x.PickRandom(heroClassIds))
.RuleFor(x => x.HeroClass, x =>
new HeroClass(x.PickRandom(HeroClasses)));

var heroesToSeed = heroesFaker.Generate(2);
await questeloperDbContext.Heroes.AddRangeAsync(heroesToSeed);
await questeloperDbContext.SaveChangesAsync();

logger.LogInformation("Generating heroes succesful!");
}

private async Task GenerateCategories()
{
logger.LogInformation("Generating categories...");

var categoriesFaker = new Faker<Category>()
.RuleFor(x => x.CategoryName,
x => new CategoryName(x.Lorem.Sentence(3)));

var categoriesToSeed = categoriesFaker.Generate(5);
await questeloperDbContext.Categories.AddRangeAsync(categoriesToSeed);
await questeloperDbContext.SaveChangesAsync();

logger.LogInformation("Generating categories succesful!");
}

private async Task GenerateQuestions()
{
logger.LogInformation("Generating questions...");

var categories = await questeloperDbContext.Categories.ToListAsync();
var enemyIds = await questeloperDbContext.Enemies.Select(x => x.Id).ToListAsync();

Expand Down Expand Up @@ -87,10 +114,14 @@ private async Task GenerateQuestions()

await Task.WhenAll(addMultipleQuestionsTask, addTextAnswerQuestionsTask);
await questeloperDbContext.SaveChangesAsync();

logger.LogInformation("Generating questions succesfull!");
}

private async Task GenerateEnemies()
{
logger.LogInformation("Generating enemies...");

var enemiesFaker = new Faker<Enemy>()
.RuleFor(x => x.Name, x => new EnemyName(x.Lorem.Word()))
.RuleFor(x => x.HealthPoints, x => new HealthPoints(x.Random.Int(1, 100)))
Expand All @@ -100,10 +131,14 @@ private async Task GenerateEnemies()

await questeloperDbContext.Enemies.AddRangeAsync(enemiesToSeed);
await questeloperDbContext.SaveChangesAsync();

logger.LogInformation("Generating enemies succesfull!");
}

private async Task GenerateUsers()
{
logger.LogInformation("Generating users...");

var usersFaker = new Faker<User>()
.RuleFor(x => x.NickName, x => new NickName(x.Person.UserName))
.RuleFor(x => x.EmailAddress, x => new EmailAddress(x.Person.Email))
Expand All @@ -116,5 +151,9 @@ private async Task GenerateUsers()

await questeloperDbContext.Users.AddRangeAsync(usersToSeed);
await questeloperDbContext.SaveChangesAsync();

logger.LogInformation("Generating users succesfull!");
}

# endregion
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,6 @@ public void Configure(EntityTypeBuilder<Hero> builder)
e => new Level(e))
.HasMaxLength(100);

builder
.Property(h => h.HeroClass)
.HasConversion(h => h.Value,
h => new HeroClass(h))
.IsRequired();

builder
.Property(h => h.HealthPoints)
.HasConversion(h => h.Points,
Expand All @@ -45,5 +39,10 @@ public void Configure(EntityTypeBuilder<Hero> builder)
.HasConversion(h => h.Points,
h => new ManaPoints(h))
.IsRequired();

builder
.HasOne(h => h.HeroClass)
.WithMany(c => c.Heroes)
.HasForeignKey(e => e.HeroClassId);
}
}
Loading

0 comments on commit dfde8fa

Please sign in to comment.