Skip to content

Commit 53acb07

Browse files
authored
Fix cannot use resource from hero inventory (#154)
* fix hero inventory not loaded correctly * fix choose building workflow that keep renavigate between dorf2.php * fix bot don't use gold to complete building if first building was short but other is long * increase delay when use item from hero inventory
1 parent d524894 commit 53acb07

7 files changed

Lines changed: 144 additions & 102 deletions

File tree

MainCore/Commands/Features/UpgradeBuilding/GetBuildPlanCommand.cs

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ private static async ValueTask<Result<NormalBuildPlan>> HandleAsync(
1515
GetLayoutBuildingsCommand.Handler getLayoutBuildingsQuery,
1616
DeleteJobByIdCommand.Handler deleteJobByIdCommand,
1717
AddJobCommand.Handler addJobCommand,
18-
ValidateJobCompleteCommand.Handler validateJobCompleteCommand,
18+
ValidatePlanCompleteCommand.Handler validatePlanCompleteCommand,
1919
ILogger logger,
2020
IRxQueue rxQueue,
2121
CancellationToken cancellationToken
@@ -27,12 +27,6 @@ CancellationToken cancellationToken
2727
{
2828
if (cancellationToken.IsCancellationRequested) return Cancel.Error;
2929

30-
var result = await toDorfCommand.HandleAsync(new(2), cancellationToken);
31-
if (result.IsFailed) return result;
32-
33-
result = await updateBuildingCommand.HandleAsync(new(villageId), cancellationToken);
34-
if (result.IsFailed) return result;
35-
3630
var (_, isFailed, job, errors) = await getJobQuery.HandleAsync(new(accountId, villageId), cancellationToken);
3731
if (isFailed) return Result.Fail(errors);
3832

@@ -56,15 +50,34 @@ CancellationToken cancellationToken
5650
}
5751

5852
var plan = JsonSerializer.Deserialize<NormalBuildPlan>(job.Content)!;
53+
Result result;
54+
if (plan.Type.IsResourceBonus())
55+
{
56+
result = await toDorfCommand.HandleAsync(new(1), cancellationToken);
57+
if (result.IsFailed) return result;
58+
59+
result = await updateBuildingCommand.HandleAsync(new(villageId), cancellationToken);
60+
if (result.IsFailed) return result;
5961

60-
var dorf = plan.Location < 19 ? 1 : 2;
61-
result = await toDorfCommand.HandleAsync(new(dorf), cancellationToken);
62-
if (result.IsFailed) return result;
62+
result = await toDorfCommand.HandleAsync(new(2), cancellationToken);
63+
if (result.IsFailed) return result;
6364

64-
result = await updateBuildingCommand.HandleAsync(new(villageId), cancellationToken);
65-
if (result.IsFailed) return result;
65+
result = await updateBuildingCommand.HandleAsync(new(villageId), cancellationToken);
66+
if (result.IsFailed) return result;
67+
}
68+
else
69+
{
70+
var dorf = plan.Location < 19 ? 1 : 2;
71+
result = await toDorfCommand.HandleAsync(new(dorf), cancellationToken);
72+
if (result.IsFailed) return result;
73+
74+
result = await updateBuildingCommand.HandleAsync(new(villageId), cancellationToken);
75+
if (result.IsFailed) return result;
76+
}
6677

67-
if (await validateJobCompleteCommand.HandleAsync(new ValidateJobCompleteCommand.Command(villageId, job), cancellationToken))
78+
var validateResult = await validatePlanCompleteCommand.HandleAsync(new(villageId, plan), cancellationToken);
79+
if (validateResult.IsFailed) return Result.Fail(validateResult.Errors);
80+
if (!validateResult.Value)
6881
{
6982
await deleteJobByIdCommand.HandleAsync(new(job.Id), cancellationToken);
7083
rxQueue.Enqueue(new JobsModified(villageId));

MainCore/Commands/Features/UpgradeBuilding/GetJobCommand.cs

Lines changed: 2 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,7 @@ AppDbContext context
2323

2424
if (queueBuildings.Count == 0)
2525
{
26-
var job = buildJobs[0];
27-
var result = IsJobValid(job, buildings, queueBuildings);
28-
if (result.IsFailed) return result;
29-
return job;
26+
return buildJobs[0];
3027
}
3128

3229
var plusActive = context.AccountsInfo
@@ -40,18 +37,13 @@ AppDbContext context
4037
{
4138
if (plusActive)
4239
{
43-
var job = buildJobs[0];
44-
var result = IsJobValid(job, buildings, queueBuildings);
45-
if (result.IsFailed) return result;
46-
return job;
40+
return buildJobs[0];
4741
}
4842

4943
if (applyRomanQueueLogic)
5044
{
5145
var (_, isFailed, job, errors) = GetJobBasedOnRomanLogic(queueBuildings, buildJobs);
5246
if (isFailed) return Result.Fail(errors);
53-
var result = IsJobValid(job, buildings, queueBuildings);
54-
if (result.IsFailed) return result;
5547
return job;
5648
}
5749
return NextExecuteError.ConstructionQueueFull(queueBuildings[0].CompleteTime);
@@ -63,8 +55,6 @@ AppDbContext context
6355
{
6456
var (_, isFailed, job, errors) = GetJobBasedOnRomanLogic(queueBuildings, buildJobs);
6557
if (isFailed) return Result.Fail(errors);
66-
var result = IsJobValid(job, buildings, queueBuildings);
67-
if (result.IsFailed) return result;
6858
return job;
6959
}
7060
return NextExecuteError.ConstructionQueueFull(queueBuildings[0].CompleteTime);
@@ -198,57 +188,5 @@ private static int CountResourceQueueBuilding(List<QueueBuilding> queueBuildings
198188
if (job.Position < resourceBuildJob.Position) return job;
199189
return resourceBuildJob;
200190
}
201-
202-
private static Result IsJobValid(JobDto job, List<Building> buildings, List<QueueBuilding> queueBuildings)
203-
{
204-
if (job.Type == JobTypeEnums.ResourceBuild) return Result.Ok();
205-
206-
var plan = JsonSerializer.Deserialize<NormalBuildPlan>(job.Content)!;
207-
if (plan.Type.IsResourceField()) return Result.Ok();
208-
209-
var oldBuilding = buildings
210-
.FirstOrDefault(x => x.Location == plan.Location);
211-
212-
if (oldBuilding is not null && oldBuilding.Type == plan.Type) return Result.Ok();
213-
214-
var errors = new List<IError>();
215-
var prerequisiteBuildings = plan.Type.GetPrerequisiteBuildings();
216-
217-
foreach (var prerequisiteBuilding in prerequisiteBuildings)
218-
{
219-
var vaild = buildings
220-
.Any(x => x.Type == prerequisiteBuilding.Type && x.Level >= prerequisiteBuilding.Level);
221-
222-
if (!vaild)
223-
{
224-
errors.Add(UpgradeBuildingError.PrerequisiteBuildingMissing(prerequisiteBuilding.Type, prerequisiteBuilding.Level));
225-
var queueBuilding = queueBuildings.Find(x => x.Type == prerequisiteBuilding.Type && x.Level == prerequisiteBuilding.Level);
226-
if (queueBuilding is not null)
227-
{
228-
errors.Add(NextExecuteError.PrerequisiteBuildingInQueue(prerequisiteBuilding.Type, prerequisiteBuilding.Level, queueBuilding.CompleteTime));
229-
}
230-
}
231-
}
232-
233-
if (!plan.Type.IsMultipleBuilding()) return errors.Count == 0 ? Result.Ok() : Result.Fail(errors);
234-
235-
var firstBuilding = buildings
236-
.Where(x => x.Type == plan.Type)
237-
.OrderByDescending(x => x.Level)
238-
.FirstOrDefault();
239-
240-
if (firstBuilding is null) return errors.Count == 0 ? Result.Ok() : Result.Fail(errors);
241-
if (firstBuilding.Location == plan.Location) return errors.Count == 0 ? Result.Ok() : Result.Fail(errors);
242-
if (firstBuilding.Level == firstBuilding.Type.GetMaxLevel()) return errors.Count == 0 ? Result.Ok() : Result.Fail(errors);
243-
244-
errors.Add(UpgradeBuildingError.PrerequisiteBuildingMissing(firstBuilding.Type, firstBuilding.Level));
245-
var prerequisiteBuildingUndercontruction = queueBuildings.Find(x => x.Type == firstBuilding.Type && x.Level == firstBuilding.Level);
246-
if (prerequisiteBuildingUndercontruction is not null)
247-
{
248-
errors.Add(NextExecuteError.PrerequisiteBuildingInQueue(firstBuilding.Type, firstBuilding.Level, prerequisiteBuildingUndercontruction.CompleteTime));
249-
}
250-
251-
return Result.Fail(errors);
252-
}
253191
}
254192
}
Lines changed: 93 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,116 @@
1-
using System.Text.Json;
2-
3-
namespace MainCore.Commands.Features.UpgradeBuilding
1+
namespace MainCore.Commands.Features.UpgradeBuilding
42
{
53
[Handler]
6-
public static partial class ValidateJobCompleteCommand
4+
public static partial class ValidatePlanCompleteCommand
75
{
8-
public sealed record Command(VillageId VillageId, JobDto job) : IVillageCommand;
6+
public sealed record Command(VillageId VillageId, NormalBuildPlan Plan) : IVillageCommand;
97

10-
private static async ValueTask<bool> HandleAsync(
8+
private static async ValueTask<Result<bool>> HandleAsync(
119
Command command,
1210
AppDbContext context,
1311
CancellationToken cancellationToken
1412
)
1513
{
1614
await Task.CompletedTask;
17-
var (villageId, job) = command;
18-
if (job.Type == JobTypeEnums.ResourceBuild) return false;
15+
var (villageId, plan) = command;
1916

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

22-
var queueBuilding = context.QueueBuildings
23-
.Where(x => x.VillageId == villageId.Value)
19+
var oldBuilding = buildings
20+
.FirstOrDefault(x => x.Location == plan.Location);
21+
22+
if (oldBuilding is not null && oldBuilding.Type == plan.Type)
23+
{
24+
if (oldBuilding.Level >= plan.Level) return false;
25+
26+
var queueBuilding = queueBuildings
2427
.Where(x => x.Location == plan.Location)
2528
.OrderByDescending(x => x.Level)
2629
.Select(x => x.Level)
2730
.FirstOrDefault();
2831

29-
if (queueBuilding >= plan.Level) return true;
32+
if (queueBuilding >= plan.Level) return false;
33+
return true;
34+
}
3035

31-
var villageBuilding = context.Buildings
32-
.Where(x => x.VillageId == villageId.Value)
33-
.Where(x => x.Location == plan.Location)
34-
.Select(x => x.Level)
36+
var errors = new List<IError>();
37+
var prerequisiteBuildings = plan.Type.GetPrerequisiteBuildings();
38+
39+
foreach (var prerequisiteBuilding in prerequisiteBuildings)
40+
{
41+
var vaild = buildings
42+
.Any(x => x.Type == prerequisiteBuilding.Type && x.Level >= prerequisiteBuilding.Level);
43+
44+
if (!vaild)
45+
{
46+
errors.Add(UpgradeBuildingError.PrerequisiteBuildingMissing(prerequisiteBuilding.Type, prerequisiteBuilding.Level));
47+
var queueBuilding = queueBuildings.Find(x => x.Type == prerequisiteBuilding.Type && x.Level == prerequisiteBuilding.Level);
48+
if (queueBuilding is not null)
49+
{
50+
errors.Add(NextExecuteError.PrerequisiteBuildingInQueue(prerequisiteBuilding.Type, prerequisiteBuilding.Level, queueBuilding.CompleteTime));
51+
}
52+
}
53+
}
54+
55+
if (!plan.Type.IsMultipleBuilding()) return errors.Count == 0 ? true : Result.Fail(errors);
56+
57+
var firstBuilding = buildings
58+
.Where(x => x.Type == plan.Type)
59+
.OrderByDescending(x => x.Level)
3560
.FirstOrDefault();
36-
if (villageBuilding >= plan.Level) return true;
3761

38-
return false;
62+
if (firstBuilding is null) return errors.Count == 0 ? true : Result.Fail(errors);
63+
if (firstBuilding.Location == plan.Location) return errors.Count == 0 ? true : Result.Fail(errors);
64+
if (firstBuilding.Level == firstBuilding.Type.GetMaxLevel()) return errors.Count == 0 ? true : Result.Fail(errors);
65+
66+
errors.Add(UpgradeBuildingError.PrerequisiteBuildingMissing(firstBuilding.Type, firstBuilding.Level));
67+
var prerequisiteBuildingUndercontruction = queueBuildings.Find(x => x.Type == firstBuilding.Type && x.Level == firstBuilding.Level);
68+
if (prerequisiteBuildingUndercontruction is not null)
69+
{
70+
errors.Add(NextExecuteError.PrerequisiteBuildingInQueue(firstBuilding.Type, firstBuilding.Level, prerequisiteBuildingUndercontruction.CompleteTime));
71+
}
72+
73+
return Result.Fail(errors);
74+
}
75+
76+
private static (List<Building>, List<QueueBuilding>) GetBuildings(this AppDbContext context, VillageId villageId)
77+
{
78+
var completeQueueBuildings = context.QueueBuildings
79+
.Where(x => x.VillageId == villageId.Value)
80+
.Where(x => x.CompleteTime < DateTime.Now)
81+
.OrderBy(x => x.Level)
82+
.ToList();
83+
84+
if (completeQueueBuildings.Count > 0)
85+
{
86+
foreach (var completeQueueBuilding in completeQueueBuildings)
87+
{
88+
if (completeQueueBuilding.Location == -1) continue;
89+
90+
var building = context.Buildings
91+
.Where(x => x.VillageId == villageId.Value)
92+
.Where(x => x.Location == completeQueueBuilding.Location)
93+
.FirstOrDefault();
94+
if (building is null) continue;
95+
96+
building.Level = completeQueueBuilding.Level;
97+
context.Remove(completeQueueBuilding);
98+
}
99+
context.SaveChanges();
100+
}
101+
102+
var buildings = context.Buildings
103+
.AsNoTracking()
104+
.Where(x => x.VillageId == villageId.Value)
105+
.ToList();
106+
107+
var queueBuildings = context.QueueBuildings
108+
.AsNoTracking()
109+
.Where(x => x.VillageId == villageId.Value)
110+
.OrderBy(x => x.CompleteTime)
111+
.ToList();
112+
113+
return (buildings, queueBuildings);
39114
}
40115
}
41116
}

MainCore/Commands/Features/UseHeroItem/ToHeroInventoryCommand.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ public sealed record Command : ICommand;
1010
private static async ValueTask<Result> HandleAsync(
1111
Command command,
1212
IChromeBrowser browser,
13+
IDelayService delayService,
1314
CancellationToken cancellationToken)
1415
{
1516
var (_, isFailed, element, errors) = await browser.GetElement(doc => InventoryParser.GetHeroAvatar(doc), cancellationToken);
@@ -22,12 +23,14 @@ static bool TabActived(IWebDriver driver)
2223
{
2324
var doc = new HtmlDocument();
2425
doc.LoadHtml(driver.PageSource);
25-
return InventoryParser.IsInventoryPage(doc);
26+
return InventoryParser.IsInventoryPage(doc) && InventoryParser.IsInventoryLoaded(doc);
2627
}
2728

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

32+
await delayService.DelayTask(cancellationToken);
33+
3134
return Result.Ok();
3235
}
3336
}

MainCore/Commands/Features/UseHeroItem/UseHeroResourceCommand.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ private static async ValueTask<Result> HandleAsync(
1111
UpdateInventoryCommand.Handler updateInventoryCommand,
1212
ValidateEnoughResourceCommand.Handler validateEnoughResourceCommand,
1313
UseHeroItemCommand.Handler useHeroItemCommand,
14+
IDelayService delayService,
1415
CancellationToken cancellationToken)
1516
{
1617
var (accountId, resource) = command;
@@ -40,6 +41,7 @@ private static async ValueTask<Result> HandleAsync(
4041
if (result.IsFailed) return result;
4142
}
4243

44+
await delayService.DelayClick(cancellationToken);
4345
return Result.Ok();
4446
}
4547

MainCore/Enums/BuildingEnums.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,19 @@ public static List<PrerequisiteBuilding> GetPrerequisiteBuildings(this BuildingE
260260
};
261261
}
262262

263+
public static bool IsResourceBonus(this BuildingEnums building)
264+
{
265+
return building switch
266+
{
267+
BuildingEnums.Sawmill => true,
268+
BuildingEnums.Brickyard => true,
269+
BuildingEnums.IronFoundry => true,
270+
BuildingEnums.Bakery => true,
271+
BuildingEnums.GrainMill => true,
272+
_ => false,
273+
};
274+
}
275+
263276
public static bool IsResourceField(this BuildingEnums building)
264277
{
265278
int buildingInt = (int)building;

MainCore/Tasks/CompleteImmediatelyTask.cs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,11 @@ public override bool CanStart(AppDbContext context)
3838
var completeImmediatelyMinimumTime = context.ByName(VillageId, VillageSettingEnums.CompleteImmediatelyTime);
3939
var requiredTime = DateTime.Now.AddMinutes(completeImmediatelyMinimumTime);
4040

41-
var firstQueueBuildingCompleteTime = queueBuildings
42-
.OrderBy(x => x.CompleteTime)
43-
.Select(x => x.CompleteTime)
44-
.FirstOrDefault();
41+
var anyBuilding = queueBuildings
42+
.Where(x => x.CompleteTime > requiredTime)
43+
.Any();
4544

46-
if (requiredTime > firstQueueBuildingCompleteTime) return false;
47-
return true;
45+
return anyBuilding;
4846
}
4947
}
5048

0 commit comments

Comments
 (0)