Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 26 additions & 13 deletions MainCore/Commands/Features/UpgradeBuilding/GetBuildPlanCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ private static async ValueTask<Result<NormalBuildPlan>> HandleAsync(
GetLayoutBuildingsCommand.Handler getLayoutBuildingsQuery,
DeleteJobByIdCommand.Handler deleteJobByIdCommand,
AddJobCommand.Handler addJobCommand,
ValidateJobCompleteCommand.Handler validateJobCompleteCommand,
ValidatePlanCompleteCommand.Handler validatePlanCompleteCommand,
ILogger logger,
IRxQueue rxQueue,
CancellationToken cancellationToken
Expand All @@ -27,12 +27,6 @@ CancellationToken cancellationToken
{
if (cancellationToken.IsCancellationRequested) return Cancel.Error;

var result = await toDorfCommand.HandleAsync(new(2), cancellationToken);
if (result.IsFailed) return result;

result = await updateBuildingCommand.HandleAsync(new(villageId), cancellationToken);
if (result.IsFailed) return result;

var (_, isFailed, job, errors) = await getJobQuery.HandleAsync(new(accountId, villageId), cancellationToken);
if (isFailed) return Result.Fail(errors);

Expand All @@ -56,15 +50,34 @@ CancellationToken cancellationToken
}

var plan = JsonSerializer.Deserialize<NormalBuildPlan>(job.Content)!;
Result result;
if (plan.Type.IsResourceBonus())
{
result = await toDorfCommand.HandleAsync(new(1), cancellationToken);
if (result.IsFailed) return result;

result = await updateBuildingCommand.HandleAsync(new(villageId), cancellationToken);
if (result.IsFailed) return result;

var dorf = plan.Location < 19 ? 1 : 2;
result = await toDorfCommand.HandleAsync(new(dorf), cancellationToken);
if (result.IsFailed) return result;
result = await toDorfCommand.HandleAsync(new(2), cancellationToken);
if (result.IsFailed) return result;

result = await updateBuildingCommand.HandleAsync(new(villageId), cancellationToken);
if (result.IsFailed) return result;
result = await updateBuildingCommand.HandleAsync(new(villageId), cancellationToken);
if (result.IsFailed) return result;
}
else
{
var dorf = plan.Location < 19 ? 1 : 2;
result = await toDorfCommand.HandleAsync(new(dorf), cancellationToken);
if (result.IsFailed) return result;

result = await updateBuildingCommand.HandleAsync(new(villageId), cancellationToken);
if (result.IsFailed) return result;
}

if (await validateJobCompleteCommand.HandleAsync(new ValidateJobCompleteCommand.Command(villageId, job), cancellationToken))
var validateResult = await validatePlanCompleteCommand.HandleAsync(new(villageId, plan), cancellationToken);
if (validateResult.IsFailed) return Result.Fail(validateResult.Errors);
if (!validateResult.Value)
{
await deleteJobByIdCommand.HandleAsync(new(job.Id), cancellationToken);
rxQueue.Enqueue(new JobsModified(villageId));
Expand Down
66 changes: 2 additions & 64 deletions MainCore/Commands/Features/UpgradeBuilding/GetJobCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,11 @@
var buildJobs = context.GetBuildJobs(villageId);
if (buildJobs.Count == 0) return UpgradeBuildingError.BuildingJobQueueEmpty;

var (buildings, queueBuildings) = context.GetBuildings(villageId);

Check warning on line 22 in MainCore/Commands/Features/UpgradeBuilding/GetJobCommand.cs

View workflow job for this annotation

GitHub Actions / Build

Remove the unused local variable 'buildings'. (https://rules.sonarsource.com/csharp/RSPEC-1481)

if (queueBuildings.Count == 0)
{
var job = buildJobs[0];
var result = IsJobValid(job, buildings, queueBuildings);
if (result.IsFailed) return result;
return job;
return buildJobs[0];
}

var plusActive = context.AccountsInfo
Expand All @@ -40,18 +37,13 @@
{
if (plusActive)
{
var job = buildJobs[0];
var result = IsJobValid(job, buildings, queueBuildings);
if (result.IsFailed) return result;
return job;
return buildJobs[0];
}

if (applyRomanQueueLogic)
{
var (_, isFailed, job, errors) = GetJobBasedOnRomanLogic(queueBuildings, buildJobs);
if (isFailed) return Result.Fail(errors);
var result = IsJobValid(job, buildings, queueBuildings);
if (result.IsFailed) return result;
return job;
}
return NextExecuteError.ConstructionQueueFull(queueBuildings[0].CompleteTime);
Expand All @@ -63,8 +55,6 @@
{
var (_, isFailed, job, errors) = GetJobBasedOnRomanLogic(queueBuildings, buildJobs);
if (isFailed) return Result.Fail(errors);
var result = IsJobValid(job, buildings, queueBuildings);
if (result.IsFailed) return result;
return job;
}
return NextExecuteError.ConstructionQueueFull(queueBuildings[0].CompleteTime);
Expand Down Expand Up @@ -198,57 +188,5 @@
if (job.Position < resourceBuildJob.Position) return job;
return resourceBuildJob;
}

private static Result IsJobValid(JobDto job, List<Building> buildings, List<QueueBuilding> queueBuildings)
{
if (job.Type == JobTypeEnums.ResourceBuild) return Result.Ok();

var plan = JsonSerializer.Deserialize<NormalBuildPlan>(job.Content)!;
if (plan.Type.IsResourceField()) return Result.Ok();

var oldBuilding = buildings
.FirstOrDefault(x => x.Location == plan.Location);

if (oldBuilding is not null && oldBuilding.Type == plan.Type) return Result.Ok();

var errors = new List<IError>();
var prerequisiteBuildings = plan.Type.GetPrerequisiteBuildings();

foreach (var prerequisiteBuilding in prerequisiteBuildings)
{
var vaild = buildings
.Any(x => x.Type == prerequisiteBuilding.Type && x.Level >= prerequisiteBuilding.Level);

if (!vaild)
{
errors.Add(UpgradeBuildingError.PrerequisiteBuildingMissing(prerequisiteBuilding.Type, prerequisiteBuilding.Level));
var queueBuilding = queueBuildings.Find(x => x.Type == prerequisiteBuilding.Type && x.Level == prerequisiteBuilding.Level);
if (queueBuilding is not null)
{
errors.Add(NextExecuteError.PrerequisiteBuildingInQueue(prerequisiteBuilding.Type, prerequisiteBuilding.Level, queueBuilding.CompleteTime));
}
}
}

if (!plan.Type.IsMultipleBuilding()) return errors.Count == 0 ? Result.Ok() : Result.Fail(errors);

var firstBuilding = buildings
.Where(x => x.Type == plan.Type)
.OrderByDescending(x => x.Level)
.FirstOrDefault();

if (firstBuilding is null) return errors.Count == 0 ? Result.Ok() : Result.Fail(errors);
if (firstBuilding.Location == plan.Location) return errors.Count == 0 ? Result.Ok() : Result.Fail(errors);
if (firstBuilding.Level == firstBuilding.Type.GetMaxLevel()) return errors.Count == 0 ? Result.Ok() : Result.Fail(errors);

errors.Add(UpgradeBuildingError.PrerequisiteBuildingMissing(firstBuilding.Type, firstBuilding.Level));
var prerequisiteBuildingUndercontruction = queueBuildings.Find(x => x.Type == firstBuilding.Type && x.Level == firstBuilding.Level);
if (prerequisiteBuildingUndercontruction is not null)
{
errors.Add(NextExecuteError.PrerequisiteBuildingInQueue(firstBuilding.Type, firstBuilding.Level, prerequisiteBuildingUndercontruction.CompleteTime));
}

return Result.Fail(errors);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,41 +1,116 @@
using System.Text.Json;

namespace MainCore.Commands.Features.UpgradeBuilding
namespace MainCore.Commands.Features.UpgradeBuilding
{
[Handler]
public static partial class ValidateJobCompleteCommand
public static partial class ValidatePlanCompleteCommand
{
public sealed record Command(VillageId VillageId, JobDto job) : IVillageCommand;
public sealed record Command(VillageId VillageId, NormalBuildPlan Plan) : IVillageCommand;

private static async ValueTask<bool> HandleAsync(
private static async ValueTask<Result<bool>> HandleAsync(
Command command,
AppDbContext context,
CancellationToken cancellationToken

Check warning on line 11 in MainCore/Commands/Features/UpgradeBuilding/ValidateJobCompleteCommand.cs

View workflow job for this annotation

GitHub Actions / Build

Remove this unused method parameter 'cancellationToken'. (https://rules.sonarsource.com/csharp/RSPEC-1172)
)
{
await Task.CompletedTask;
var (villageId, job) = command;
if (job.Type == JobTypeEnums.ResourceBuild) return false;
var (villageId, plan) = command;

var plan = JsonSerializer.Deserialize<NormalBuildPlan>(job.Content)!;
var (buildings, queueBuildings) = context.GetBuildings(villageId);

var queueBuilding = context.QueueBuildings
.Where(x => x.VillageId == villageId.Value)
var oldBuilding = buildings
.FirstOrDefault(x => x.Location == plan.Location);

if (oldBuilding is not null && oldBuilding.Type == plan.Type)
{
if (oldBuilding.Level >= plan.Level) return false;

var queueBuilding = queueBuildings
.Where(x => x.Location == plan.Location)
.OrderByDescending(x => x.Level)
.Select(x => x.Level)
.FirstOrDefault();

if (queueBuilding >= plan.Level) return true;
if (queueBuilding >= plan.Level) return false;
return true;
}

var villageBuilding = context.Buildings
.Where(x => x.VillageId == villageId.Value)
.Where(x => x.Location == plan.Location)
.Select(x => x.Level)
var errors = new List<IError>();
var prerequisiteBuildings = plan.Type.GetPrerequisiteBuildings();

foreach (var prerequisiteBuilding in prerequisiteBuildings)
{
var vaild = buildings
.Any(x => x.Type == prerequisiteBuilding.Type && x.Level >= prerequisiteBuilding.Level);

if (!vaild)
{
errors.Add(UpgradeBuildingError.PrerequisiteBuildingMissing(prerequisiteBuilding.Type, prerequisiteBuilding.Level));
var queueBuilding = queueBuildings.Find(x => x.Type == prerequisiteBuilding.Type && x.Level == prerequisiteBuilding.Level);
if (queueBuilding is not null)
{
errors.Add(NextExecuteError.PrerequisiteBuildingInQueue(prerequisiteBuilding.Type, prerequisiteBuilding.Level, queueBuilding.CompleteTime));
}
}
}

if (!plan.Type.IsMultipleBuilding()) return errors.Count == 0 ? true : Result.Fail(errors);

Check warning on line 55 in MainCore/Commands/Features/UpgradeBuilding/ValidateJobCompleteCommand.cs

View workflow job for this annotation

GitHub Actions / Build

Remove the unnecessary Boolean literal(s). (https://rules.sonarsource.com/csharp/RSPEC-1125)

var firstBuilding = buildings
.Where(x => x.Type == plan.Type)
.OrderByDescending(x => x.Level)
.FirstOrDefault();
if (villageBuilding >= plan.Level) return true;

return false;
if (firstBuilding is null) return errors.Count == 0 ? true : Result.Fail(errors);

Check warning on line 62 in MainCore/Commands/Features/UpgradeBuilding/ValidateJobCompleteCommand.cs

View workflow job for this annotation

GitHub Actions / Build

Remove the unnecessary Boolean literal(s). (https://rules.sonarsource.com/csharp/RSPEC-1125)
if (firstBuilding.Location == plan.Location) return errors.Count == 0 ? true : Result.Fail(errors);

Check warning on line 63 in MainCore/Commands/Features/UpgradeBuilding/ValidateJobCompleteCommand.cs

View workflow job for this annotation

GitHub Actions / Build

Remove the unnecessary Boolean literal(s). (https://rules.sonarsource.com/csharp/RSPEC-1125)
if (firstBuilding.Level == firstBuilding.Type.GetMaxLevel()) return errors.Count == 0 ? true : Result.Fail(errors);

Check warning on line 64 in MainCore/Commands/Features/UpgradeBuilding/ValidateJobCompleteCommand.cs

View workflow job for this annotation

GitHub Actions / Build

Remove the unnecessary Boolean literal(s). (https://rules.sonarsource.com/csharp/RSPEC-1125)

errors.Add(UpgradeBuildingError.PrerequisiteBuildingMissing(firstBuilding.Type, firstBuilding.Level));
var prerequisiteBuildingUndercontruction = queueBuildings.Find(x => x.Type == firstBuilding.Type && x.Level == firstBuilding.Level);
if (prerequisiteBuildingUndercontruction is not null)
{
errors.Add(NextExecuteError.PrerequisiteBuildingInQueue(firstBuilding.Type, firstBuilding.Level, prerequisiteBuildingUndercontruction.CompleteTime));
}

return Result.Fail(errors);
}

private static (List<Building>, List<QueueBuilding>) GetBuildings(this AppDbContext context, VillageId villageId)
{
var completeQueueBuildings = context.QueueBuildings
.Where(x => x.VillageId == villageId.Value)
.Where(x => x.CompleteTime < DateTime.Now)
.OrderBy(x => x.Level)
.ToList();

if (completeQueueBuildings.Count > 0)
{
foreach (var completeQueueBuilding in completeQueueBuildings)
{
if (completeQueueBuilding.Location == -1) continue;

var building = context.Buildings
.Where(x => x.VillageId == villageId.Value)
.Where(x => x.Location == completeQueueBuilding.Location)
.FirstOrDefault();
if (building is null) continue;

building.Level = completeQueueBuilding.Level;
context.Remove(completeQueueBuilding);
}
context.SaveChanges();
}

var buildings = context.Buildings
.AsNoTracking()
.Where(x => x.VillageId == villageId.Value)
.ToList();

var queueBuildings = context.QueueBuildings
.AsNoTracking()
.Where(x => x.VillageId == villageId.Value)
.OrderBy(x => x.CompleteTime)
.ToList();

return (buildings, queueBuildings);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public sealed record Command : ICommand;
private static async ValueTask<Result> HandleAsync(
Command command,
IChromeBrowser browser,
IDelayService delayService,
CancellationToken cancellationToken)
{
var (_, isFailed, element, errors) = await browser.GetElement(doc => InventoryParser.GetHeroAvatar(doc), cancellationToken);
Expand All @@ -22,12 +23,14 @@ static bool TabActived(IWebDriver driver)
{
var doc = new HtmlDocument();
doc.LoadHtml(driver.PageSource);
return InventoryParser.IsInventoryPage(doc);
return InventoryParser.IsInventoryPage(doc) && InventoryParser.IsInventoryLoaded(doc);
}

result = await browser.Wait(TabActived, cancellationToken);
if (result.IsFailed) return result;

await delayService.DelayTask(cancellationToken);

return Result.Ok();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ private static async ValueTask<Result> HandleAsync(
UpdateInventoryCommand.Handler updateInventoryCommand,
ValidateEnoughResourceCommand.Handler validateEnoughResourceCommand,
UseHeroItemCommand.Handler useHeroItemCommand,
IDelayService delayService,
CancellationToken cancellationToken)
{
var (accountId, resource) = command;
Expand Down Expand Up @@ -40,6 +41,7 @@ private static async ValueTask<Result> HandleAsync(
if (result.IsFailed) return result;
}

await delayService.DelayClick(cancellationToken);
return Result.Ok();
}

Expand Down
13 changes: 13 additions & 0 deletions MainCore/Enums/BuildingEnums.cs
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,19 @@ public static List<PrerequisiteBuilding> GetPrerequisiteBuildings(this BuildingE
};
}

public static bool IsResourceBonus(this BuildingEnums building)
{
return building switch
{
BuildingEnums.Sawmill => true,
BuildingEnums.Brickyard => true,
BuildingEnums.IronFoundry => true,
BuildingEnums.Bakery => true,
BuildingEnums.GrainMill => true,
_ => false,
};
}

public static bool IsResourceField(this BuildingEnums building)
{
int buildingInt = (int)building;
Expand Down
10 changes: 4 additions & 6 deletions MainCore/Tasks/CompleteImmediatelyTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,11 @@ public override bool CanStart(AppDbContext context)
var completeImmediatelyMinimumTime = context.ByName(VillageId, VillageSettingEnums.CompleteImmediatelyTime);
var requiredTime = DateTime.Now.AddMinutes(completeImmediatelyMinimumTime);

var firstQueueBuildingCompleteTime = queueBuildings
.OrderBy(x => x.CompleteTime)
.Select(x => x.CompleteTime)
.FirstOrDefault();
var anyBuilding = queueBuildings
.Where(x => x.CompleteTime > requiredTime)
.Any();

if (requiredTime > firstQueueBuildingCompleteTime) return false;
return true;
return anyBuilding;
}
}

Expand Down
Loading