Refactoring: plan actions as classes
This commit is contained in:
parent
d4ad7ec40c
commit
1b053de16a
62
src/Plan/CropBuildingPlan.ts
Normal file
62
src/Plan/CropBuildingPlan.ts
Normal file
@ -0,0 +1,62 @@
|
||||
import { ConstructionPlan } from '../Village/VillageController';
|
||||
import { ResourceType } from '../Core/ResourceType';
|
||||
import { isBuildingPlanned } from '../Queue/Task';
|
||||
import { UpgradeBuildingTask } from '../Handler/Task/UpgradeBuildingTask';
|
||||
import { first } from '../Helpers/Collection';
|
||||
import { VillageState } from '../Village/VillageState';
|
||||
import { VillageTaskCollection } from '../Village/VillageTaskCollection';
|
||||
import { VillageStorage } from '../Storage/VillageStorage';
|
||||
|
||||
export class CropBuildingPlan implements ConstructionPlan {
|
||||
constructor(
|
||||
private readonly state: VillageState,
|
||||
private readonly storage: VillageStorage,
|
||||
private readonly taskCollection: VillageTaskCollection
|
||||
) {}
|
||||
|
||||
execute() {
|
||||
const performance = this.state.performance;
|
||||
if (performance.crop >= 30) {
|
||||
return;
|
||||
}
|
||||
|
||||
const resourceSlots = this.storage.getResourceSlots();
|
||||
const tasks = this.state.tasks;
|
||||
|
||||
const cropSlots = resourceSlots.filter(
|
||||
(s) => s.type === ResourceType.Crop && !s.isMaxLevel
|
||||
);
|
||||
if (cropSlots.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check, if crop field is building now
|
||||
const underContraction = cropSlots.find((s) => s.isUnderConstruction);
|
||||
if (underContraction !== undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check, if we already have crop task in queue
|
||||
const cropBuildIds = cropSlots.map((s) => s.buildId);
|
||||
for (let buildId of cropBuildIds) {
|
||||
const upgradeTask = tasks.find(
|
||||
isBuildingPlanned(UpgradeBuildingTask.name, buildId, undefined)
|
||||
);
|
||||
if (upgradeTask !== undefined) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Find ready for building slots and sort them by level
|
||||
cropSlots.sort((s1, s2) => s1.level - s2.level);
|
||||
|
||||
const targetCropBuildId = first(cropSlots)?.buildId;
|
||||
if (!targetCropBuildId) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.taskCollection.addTaskAsFirst(UpgradeBuildingTask.name, {
|
||||
buildId: targetCropBuildId,
|
||||
});
|
||||
}
|
||||
}
|
70
src/Plan/WarehouseBuildingPlan.ts
Normal file
70
src/Plan/WarehouseBuildingPlan.ts
Normal file
@ -0,0 +1,70 @@
|
||||
import { ConstructionPlan } from '../Village/VillageController';
|
||||
import { isBuildingPlanned } from '../Queue/Task';
|
||||
import { UpgradeBuildingTask } from '../Handler/Task/UpgradeBuildingTask';
|
||||
import { first } from '../Helpers/Collection';
|
||||
import { TaskState, VillageState } from '../Village/VillageState';
|
||||
import { VillageTaskCollection } from '../Village/VillageTaskCollection';
|
||||
import { VillageStorage } from '../Storage/VillageStorage';
|
||||
import { BuildingSlot } from '../Core/Slot';
|
||||
|
||||
export class WarehouseBuildingPlan implements ConstructionPlan {
|
||||
constructor(
|
||||
private readonly buildTypeId: number,
|
||||
private readonly checkNeedEnlargeFunc: (task: TaskState) => boolean,
|
||||
private readonly state: VillageState,
|
||||
private readonly storage: VillageStorage,
|
||||
private readonly taskCollection: VillageTaskCollection
|
||||
) {}
|
||||
|
||||
execute() {
|
||||
const storageSlots = this.findStorageSlots();
|
||||
if (storageSlots.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check, if warehouse is building now
|
||||
const underConstructionSlot = storageSlots.find((s) => s.isUnderConstruction);
|
||||
if (underConstructionSlot !== undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.isWarehouseInBuildingQueue(storageSlots)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const needStorageEnlargeTasks = this.state.tasks.filter(this.checkNeedEnlargeFunc);
|
||||
if (needStorageEnlargeTasks.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const firstSlot = first(storageSlots);
|
||||
if (firstSlot) {
|
||||
this.taskCollection.addTask(UpgradeBuildingTask.name, {
|
||||
buildId: firstSlot.buildId,
|
||||
buildTypeId: this.buildTypeId,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private findStorageSlots() {
|
||||
const buildingSlots = this.storage.getBuildingSlots();
|
||||
|
||||
return buildingSlots.filter(
|
||||
(slot) => slot.buildTypeId === this.buildTypeId && !slot.isMaxLevel
|
||||
);
|
||||
}
|
||||
|
||||
private isWarehouseInBuildingQueue(storageSlots: ReadonlyArray<BuildingSlot>): boolean {
|
||||
const storageBuildIds = storageSlots.map((slot) => slot.buildId);
|
||||
for (let buildId of storageBuildIds) {
|
||||
const upgradeTask = this.state.tasks.find(
|
||||
isBuildingPlanned(UpgradeBuildingTask.name, buildId, this.buildTypeId)
|
||||
);
|
||||
if (upgradeTask !== undefined) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
@ -15,6 +15,7 @@ export interface Args {
|
||||
troopId?: number;
|
||||
troopResources?: ResourcesInterface;
|
||||
trainCount?: number;
|
||||
count?: number;
|
||||
resources?: ResourcesInterface;
|
||||
coordinates?: CoordinatesInterface;
|
||||
unitId?: number;
|
||||
|
@ -5,12 +5,14 @@ import { Resources } from '../Core/Resources';
|
||||
import { MerchantsInfo } from '../Core/Market';
|
||||
import { VillageStorage } from '../Storage/VillageStorage';
|
||||
import { ReceiveResourcesMode } from '../Core/Village';
|
||||
import { ResourceType } from '../Core/ResourceType';
|
||||
import { UpgradeBuildingTask } from '../Handler/Task/UpgradeBuildingTask';
|
||||
import { GARNER_ID, WAREHOUSE_ID } from '../Core/Buildings';
|
||||
import { first } from '../Helpers/Collection';
|
||||
import { isBuildingPlanned } from '../Queue/Task';
|
||||
import { TaskId } from '../Queue/TaskId';
|
||||
import { CropBuildingPlan } from '../Plan/CropBuildingPlan';
|
||||
import { WarehouseBuildingPlan } from '../Plan/WarehouseBuildingPlan';
|
||||
|
||||
export interface ConstructionPlan {
|
||||
execute(): void;
|
||||
}
|
||||
|
||||
export class VillageController {
|
||||
private readonly villageId: number;
|
||||
@ -157,105 +159,20 @@ export class VillageController {
|
||||
if (this.state.tasks.length >= 100) {
|
||||
return;
|
||||
}
|
||||
this.planCropBuilding();
|
||||
this.planWarehouseBuilding();
|
||||
this.planGranaryBuilding();
|
||||
}
|
||||
|
||||
private planCropBuilding() {
|
||||
const performance = this.state.performance;
|
||||
if (performance.crop >= 30) {
|
||||
return;
|
||||
}
|
||||
|
||||
const resourceSlots = this.storage.getResourceSlots();
|
||||
const tasks = this.taskCollection.getTasks();
|
||||
|
||||
const cropSlots = resourceSlots.filter(
|
||||
(s) => s.type === ResourceType.Crop && !s.isMaxLevel
|
||||
);
|
||||
if (cropSlots.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check, if crop field is building now
|
||||
const underContraction = cropSlots.find((s) => s.isUnderConstruction);
|
||||
if (underContraction !== undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check, if we already have crop task in queue
|
||||
const cropBuildIds = cropSlots.map((s) => s.buildId);
|
||||
for (let buildId of cropBuildIds) {
|
||||
const upgradeTask = tasks.find(
|
||||
isBuildingPlanned(UpgradeBuildingTask.name, buildId, undefined)
|
||||
);
|
||||
if (upgradeTask !== undefined) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Find ready for building slots and sort them by level
|
||||
cropSlots.sort((s1, s2) => s1.level - s2.level);
|
||||
|
||||
const targetCropBuildId = first(cropSlots)?.buildId;
|
||||
if (!targetCropBuildId) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.taskCollection.addTaskAsFirst(UpgradeBuildingTask.name, {
|
||||
buildId: targetCropBuildId,
|
||||
});
|
||||
}
|
||||
|
||||
private planWarehouseBuilding(): void {
|
||||
this.planStorageBuilding(WAREHOUSE_ID, (t) => !t.isEnoughWarehouseCapacity);
|
||||
}
|
||||
|
||||
private planGranaryBuilding(): void {
|
||||
this.planStorageBuilding(GARNER_ID, (t) => !t.isEnoughGranaryCapacity);
|
||||
}
|
||||
|
||||
private planStorageBuilding(
|
||||
buildTypeId: number,
|
||||
checkNeedEnlargeFunc: (task: TaskState) => boolean
|
||||
): void {
|
||||
const buildingSlots = this.storage.getBuildingSlots();
|
||||
|
||||
const storageSlots = buildingSlots.filter(
|
||||
(s) => s.buildTypeId === buildTypeId && !s.isMaxLevel
|
||||
);
|
||||
if (storageSlots.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check, if warehouse is building now
|
||||
const underConstruction = storageSlots.find((s) => s.isUnderConstruction);
|
||||
if (underConstruction !== undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
const tasks = this.state.tasks;
|
||||
|
||||
// Check, if we have warehouse is in building queue
|
||||
const storageBuildIds = storageSlots.map((s) => s.buildId);
|
||||
for (let buildId of storageBuildIds) {
|
||||
const upgradeTask = tasks.find(
|
||||
isBuildingPlanned(UpgradeBuildingTask.name, buildId, buildTypeId)
|
||||
);
|
||||
if (upgradeTask !== undefined) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const needStorageEnlargeTasks = tasks.filter(checkNeedEnlargeFunc);
|
||||
if (needStorageEnlargeTasks.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const firstSlot = first(storageSlots);
|
||||
if (firstSlot) {
|
||||
this.addTask(UpgradeBuildingTask.name, { buildId: firstSlot.buildId, buildTypeId });
|
||||
}
|
||||
new CropBuildingPlan(this.state, this.storage, this.taskCollection).execute();
|
||||
new WarehouseBuildingPlan(
|
||||
WAREHOUSE_ID,
|
||||
(t) => !t.isEnoughWarehouseCapacity,
|
||||
this.state,
|
||||
this.storage,
|
||||
this.taskCollection
|
||||
).execute();
|
||||
new WarehouseBuildingPlan(
|
||||
GARNER_ID,
|
||||
(t) => !t.isEnoughGranaryCapacity,
|
||||
this.state,
|
||||
this.storage,
|
||||
this.taskCollection
|
||||
).execute();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user