diff --git a/src/ControlPanel.ts b/src/ControlPanel.ts index 31ae4fe..ecdbb7b 100644 --- a/src/ControlPanel.ts +++ b/src/ControlPanel.ts @@ -111,7 +111,8 @@ export class ControlPanel { const getBuildingsInQueue = () => this.villageFactory - .createTaskCollection(villageId) + .getById(villageId) + .taskCollection() .getTasks() .filter((t) => t.name === UpgradeBuildingTask.name) .map((t) => t.args.buildId || 0); @@ -136,7 +137,7 @@ export class ControlPanel { const buildPage = new BuildingPageController( this.scheduler, getBuildingPageAttributes(), - this.villageFactory.createController(villageId) + this.villageFactory.getById(villageId).controller() ); buildPage.run(); } diff --git a/src/Dashboard/Store.ts b/src/Dashboard/Store.ts index 43e7f97..2c0f10a 100644 --- a/src/Dashboard/Store.ts +++ b/src/Dashboard/Store.ts @@ -76,7 +76,7 @@ export function createStore(villageFactory: VillageFactory) { }, actions: { [Actions.OpenVillageEditor]({ commit }, { villageId }) { - const state = villageFactory.createState(villageId); + const state = villageFactory.getById(villageId).state(); const settings = state.settings; commit(Mutations.SetVillageSettings, { villageId: state.id, @@ -89,7 +89,7 @@ export function createStore(villageFactory: VillageFactory) { [Actions.SaveVillageSettings]({ state }) { const villageName = state.villageSettings.villageName; const villageId = state.villageSettings.villageId; - const villageState = villageFactory.createState(villageId); + const villageState = villageFactory.getById(villageId).state(); const newSettings: VillageSettings = { sendResourcesThreshold: state.villageSettings.sendResourcesThreshold || @@ -104,19 +104,19 @@ export function createStore(villageFactory: VillageFactory) { notify(`Настройки для ${villageName} сохранены`); }, [Actions.ToggleVillageReceiveMode]({}, { villageId }) { - const controller = villageFactory.createController(villageId); + const controller = villageFactory.getById(villageId).controller(); controller.toggleReceiveResourcesMode(); }, [Actions.RemoveVillageTask]({}, { villageId, taskId }) { - const controller = villageFactory.createController(villageId); + const controller = villageFactory.getById(villageId).controller(); controller.removeTask(taskId); }, [Actions.UpVillageTask]({}, { villageId, taskId }) { - const controller = villageFactory.createController(villageId); + const controller = villageFactory.getById(villageId).controller(); controller.upTask(taskId); }, [Actions.DownVillageTask]({}, { villageId, taskId }) { - const controller = villageFactory.createController(villageId); + const controller = villageFactory.getById(villageId).controller(); controller.downTask(taskId); }, }, diff --git a/src/Grabber/GrabberManager.ts b/src/Grabber/GrabberManager.ts index 859c71b..39903be 100644 --- a/src/Grabber/GrabberManager.ts +++ b/src/Grabber/GrabberManager.ts @@ -24,8 +24,8 @@ export class GrabberManager { } private createGrabbers(): Array { - const storage = this.factory.createStorageForActiveVillage(); - const taskCollection = this.factory.createTaskCollectionForActiveVillage(); + const storage = this.factory.active().storage(); + const taskCollection = this.factory.active().taskCollection(); const grabbers: Array = []; grabbers.push(new VillageResourceGrabber(taskCollection, storage)); grabbers.push(new VillageOverviewPageGrabber(taskCollection, storage)); diff --git a/src/Handler/Action/BalanceHeroResourcesAction.ts b/src/Handler/Action/BalanceHeroResourcesAction.ts index 7dd5b74..55702db 100644 --- a/src/Handler/Action/BalanceHeroResourcesAction.ts +++ b/src/Handler/Action/BalanceHeroResourcesAction.ts @@ -19,11 +19,10 @@ export class BalanceHeroResourcesAction extends BaseAction { return; } - const thisVillageState = this.villageFactory.createState(thisVillageId); + const thisVillageState = this.villageFactory.getById(thisVillageId).state(); const requirements = [ thisVillageState.required.balance, - thisVillageState.commitments, thisVillageState.resources.sub(thisVillageState.warehouse.capacity), ]; diff --git a/src/Handler/Action/SendResourcesAction.ts b/src/Handler/Action/SendResourcesAction.ts index a7de9c4..ba43543 100644 --- a/src/Handler/Action/SendResourcesAction.ts +++ b/src/Handler/Action/SendResourcesAction.ts @@ -14,8 +14,8 @@ export class SendResourcesAction extends BaseAction { const storage = new ResourceTransferStorage(); const savedReport = storage.getReport(); - const fromVillage = this.villageFactory.getVillage(savedReport.fromVillageId); - const toVillage = this.villageFactory.getVillage(savedReport.toVillageId); + const fromVillage = this.villageFactory.getById(savedReport.fromVillageId).short(); + const toVillage = this.villageFactory.getById(savedReport.toVillageId).short(); const coordinates = toVillage.crd; diff --git a/src/Handler/Task/UpdateResourceContractsTask.ts b/src/Handler/Task/UpdateResourceContractsTask.ts index 851dbe5..28e34ee 100644 --- a/src/Handler/Task/UpdateResourceContractsTask.ts +++ b/src/Handler/Task/UpdateResourceContractsTask.ts @@ -12,7 +12,7 @@ export class UpdateResourceContractsTask extends BaseTask { const villages = this.factory.getAllVillages(); const tasks = villages - .map((v) => this.factory.createTaskCollection(v.id).getTasks()) + .map((v) => this.factory.getById(v.id).taskCollection().getTasks()) .reduce((acc, tasks) => acc.concat(tasks), []); const paths = uniqPaths([ diff --git a/src/Scheduler.ts b/src/Scheduler.ts index 6a554fb..f27ec5f 100644 --- a/src/Scheduler.ts +++ b/src/Scheduler.ts @@ -106,12 +106,14 @@ export class Scheduler { const villageId = task.args.villageId; // First stage - plan new tasks if needed. - const controllerForPlan = this.villageControllerFactory.createController(villageId); + const controllerForPlan = this.villageControllerFactory.getById(villageId).controller(); controllerForPlan.planTasks(); // Second stage - select isReady for production task. // We recreate controller, because need new village state. - const controllerForSelect = this.villageControllerFactory.createController(villageId); + const controllerForSelect = this.villageControllerFactory + .getById(villageId) + .controller(); const villageTask = controllerForSelect.getReadyProductionTask(); if (villageTask) { @@ -129,7 +131,7 @@ export class Scheduler { scheduleTask(name: string, args: Args, ts?: number | undefined): void { if (isProductionTask(name) && args.villageId) { - const controller = this.villageControllerFactory.createController(args.villageId); + const controller = this.villageControllerFactory.getById(args.villageId).controller(); controller.addTask(name, args); } else { this.logger.info('Schedule task', name, args, ts); @@ -161,7 +163,7 @@ export class Scheduler { const task = this.taskQueue.findById(taskId); const villageId = task ? task.args.villageId : undefined; if (villageId) { - const controller = this.villageControllerFactory.createController(villageId); + const controller = this.villageControllerFactory.getById(villageId).controller(); controller.removeTask(taskId); } this.removeTask(taskId); @@ -174,7 +176,9 @@ export class Scheduler { } if (isProductionTask(task.name) && task.args.villageId) { - const controller = this.villageControllerFactory.createController(task.args.villageId); + const controller = this.villageControllerFactory + .getById(task.args.villageId) + .controller(); controller.postponeTask(taskId, seconds); this.removeTask(taskId); } else { diff --git a/src/Village/ResourceTransfer.ts b/src/Village/ResourceTransfer.ts index 6c6c660..e650823 100644 --- a/src/Village/ResourceTransfer.ts +++ b/src/Village/ResourceTransfer.ts @@ -30,8 +30,8 @@ export class ResourceTransferCalculator { } calc(fromVillageId: number, toVillageId: number): ResourceTransferReport { - const sender = this.factory.createController(fromVillageId); - const recipient = this.factory.createController(toVillageId); + const sender = this.factory.getById(fromVillageId).controller(); + const recipient = this.factory.getById(toVillageId).controller(); let [senderReadyResources, recipientNeedResources] = this.getTransferResourcePair( sender, diff --git a/src/Village/VillageFactory.ts b/src/Village/VillageFactory.ts index e7e58bd..2eecb8e 100644 --- a/src/Village/VillageFactory.ts +++ b/src/Village/VillageFactory.ts @@ -1,71 +1,68 @@ import { VillageController } from './VillageController'; import { VillageStorage } from '../Storage/VillageStorage'; -import { VillageRepository } from './VillageRepository'; +import { VillageRepositoryInterface } from './VillageRepository'; import { VillageTaskCollection } from './VillageTaskCollection'; import { VillageState, VillageStateFactory } from './VillageState'; import { Village } from '../Core/Village'; export class VillageFactory { - private readonly villageRepository: VillageRepository; + private readonly villageRepository: VillageRepositoryInterface; - constructor(villageRepository: VillageRepository) { + constructor(villageRepository: VillageRepositoryInterface) { this.villageRepository = villageRepository; } + getById(villageId: number): IntVillageFactory { + return this.makeInternalFactory(this.villageRepository.getById(villageId)); + } + + active(): IntVillageFactory { + return this.makeInternalFactory(this.villageRepository.getActive()); + } + + private makeInternalFactory(village: Village): IntVillageFactory { + return new IntVillageFactory(village, new VillageStateFactory()); + } + getAllVillages(): Array { return this.villageRepository.all(); } - getVillage(villageId: number): Village { - return this.villageRepository.get(villageId); - } - - createStorage(villageId: number): VillageStorage { - const village = this.villageRepository.get(villageId); - return new VillageStorage(village.id); - } - - createStorageForActiveVillage(): VillageStorage { - const village = this.villageRepository.getActive(); - return this.createStorage(village.id); - } - - createTaskCollection(villageId: number): VillageTaskCollection { - const village = this.villageRepository.get(villageId); - return new VillageTaskCollection(village.id, this.createStorage(villageId)); - } - - createTaskCollectionForActiveVillage(): VillageTaskCollection { - const village = this.villageRepository.getActive(); - return this.createTaskCollection(village.id); - } - - createState(villageId: number): VillageState { - const village = this.villageRepository.get(villageId); - const stateFactory = new VillageStateFactory( - this.villageRepository, - (id: number) => this.createStorage(id), - (id: number) => this.createTaskCollection(id) - ); - return stateFactory.getVillageState(village.id); - } - getAllVillageStates(): Array { - const stateFactory = new VillageStateFactory( - this.villageRepository, - (id: number) => this.createStorage(id), - (id: number) => this.createTaskCollection(id) - ); - return stateFactory.getAllVillageStates(); + return this.villageRepository + .all() + .map((village) => this.makeInternalFactory(village).state()); + } +} + +class IntVillageFactory { + constructor( + private readonly village: Village, + private readonly stateFactory: VillageStateFactory + ) {} + + short(): Village { + return this.village; } - createController(villageId: number): VillageController { - const village = this.villageRepository.get(villageId); + storage(): VillageStorage { + return new VillageStorage(this.village.id); + } + + taskCollection(): VillageTaskCollection { + return new VillageTaskCollection(this.village.id, this.storage()); + } + + state(): VillageState { + return this.stateFactory.getVillageState(this.village, this.storage()); + } + + controller(): VillageController { return new VillageController( - village.id, - this.createStorage(village.id), - this.createTaskCollection(village.id), - this.createState(village.id) + this.village.id, + this.storage(), + this.taskCollection(), + this.state() ); } } diff --git a/src/Village/VillageRepository.ts b/src/Village/VillageRepository.ts index 8d37f58..97e04e2 100644 --- a/src/Village/VillageRepository.ts +++ b/src/Village/VillageRepository.ts @@ -4,6 +4,8 @@ import { VillageNotFound } from '../Errors'; export interface VillageRepositoryInterface { all(): Array; + getById(villageId: number): Village; + getByCrd(crd: Coordinates): Village; getActive(): Village; } @@ -12,7 +14,7 @@ export class VillageRepository implements VillageRepositoryInterface { return grabVillageList(); } - get(villageId: number): Village { + getById(villageId: number): Village { const village = this.all().find((vlg) => vlg.id === villageId); if (!village) { throw new VillageNotFound('Active village not found'); diff --git a/src/Village/VillageState.ts b/src/Village/VillageState.ts index e406a2d..56f565e 100644 --- a/src/Village/VillageState.ts +++ b/src/Village/VillageState.ts @@ -2,10 +2,7 @@ import { Village, VillageSettings } from '../Core/Village'; import { Resources } from '../Core/Resources'; import { VillageStorage } from '../Storage/VillageStorage'; import { calcGatheringTimings, GatheringTime } from '../Core/GatheringTimings'; -import { VillageRepositoryInterface } from './VillageRepository'; -import { VillageNotFound } from '../Errors'; import { OrderedProductionQueues, ProductionQueue } from '../Core/ProductionQueue'; -import { VillageTaskCollection } from './VillageTaskCollection'; import { TrainTroopTask } from '../Handler/Task/TrainTroopTask'; import { Args } from '../Queue/Args'; import { timestamp } from '../Helpers/Time'; @@ -73,7 +70,7 @@ interface ResourceLineState { active: boolean; } -interface VillageOwnState { +export interface VillageState { /** * Village id */ @@ -99,17 +96,6 @@ interface VillageOwnState { settings: VillageSettings; } -interface VillageOwnStateDictionary { - [id: number]: VillageOwnState; -} - -export interface VillageState extends VillageOwnState { - /** - * Resource commitments of this village to other (may be negative) - */ - commitments: Resources; -} - function makeResourceState( resources: Resources, current: Resources, @@ -274,19 +260,13 @@ function makeTaskState(task: TaskCore, maxResourcesForTask: Resources): TaskStat }; } -function createVillageOwnState( - village: Village, - storage: VillageStorage, - taskCollection: VillageTaskCollection -): VillageOwnState { +function createVillageState(village: Village, storage: VillageStorage): VillageState { const settings = storage.getSettings(); const resources = storage.getResources(); const capacity = storage.getWarehouseCapacity(); const performance = storage.getResourcesPerformance(); const storageState = makeWarehouseState(resources, capacity, performance); - const tasks = taskCollection - .getTasks() - .map((t) => makeTaskState(t, storageState.optimumFullness)); + const tasks = storage.getTasks().map((t) => makeTaskState(t, storageState.optimumFullness)); const queues = createTaskQueueStates(storageState, tasks, storage); const firstReadyTask = getReadyForProductionTask(queues); const requiredResources = getTaskResources(firstReadyTask); @@ -305,90 +285,8 @@ function createVillageOwnState( }; } -function createVillageOwnStates( - villages: Array, - storageFactory: VillageStorageFactory, - taskCollectionFactory: VillageTaskCollectionFactory -): VillageOwnStateDictionary { - const result: VillageOwnStateDictionary = {}; - for (let village of villages) { - result[village.id] = createVillageOwnState( - village, - storageFactory(village.id), - taskCollectionFactory(village.id) - ); - } - return result; -} - -function createVillageState( - ownState: VillageOwnState, - otherOwnStates: VillageOwnStateDictionary -): VillageState { - const otherVillageIds = Object.keys(otherOwnStates).map((key) => +key); - const reducer = (memo: Resources, shipmentVillageId: number) => { - const shipmentVillageState = otherOwnStates[shipmentVillageId]; - const shipmentVillageRequired = shipmentVillageState.required; - const shipmentVillageIncoming = shipmentVillageState.incomingResources; - const targetVillageMissing = shipmentVillageRequired.balance - .add(shipmentVillageIncoming) - .min(Resources.zero()); - return memo.add(targetVillageMissing); - }; - const commitments = otherVillageIds.reduce(reducer, Resources.zero()); - return { ...ownState, commitments }; -} - -function getVillageStates( - villages: Array, - storageFactory: VillageStorageFactory, - taskCollectionFactory: VillageTaskCollectionFactory -): Array { - const ownStates = createVillageOwnStates(villages, storageFactory, taskCollectionFactory); - return villages.map((village) => createVillageState(ownStates[village.id], ownStates)); -} - -interface VillageStorageFactory { - (villageId: number): VillageStorage; -} - -interface VillageTaskCollectionFactory { - (villageId: number): VillageTaskCollection; -} - export class VillageStateFactory { - private readonly villageRepository: VillageRepositoryInterface; - private readonly storageFactory: VillageStorageFactory; - private readonly taskCollectionFactory: VillageTaskCollectionFactory; - - constructor( - villageRepository: VillageRepositoryInterface, - storageFactory: VillageStorageFactory, - taskCollectionFactory: VillageTaskCollectionFactory - ) { - this.villageRepository = villageRepository; - this.storageFactory = storageFactory; - this.taskCollectionFactory = taskCollectionFactory; - } - - getAllVillageStates(): Array { - return getVillageStates( - this.villageRepository.all(), - this.storageFactory, - this.taskCollectionFactory - ); - } - - getVillageState(villageId: number): VillageState { - const states = getVillageStates( - this.villageRepository.all(), - this.storageFactory, - this.taskCollectionFactory - ); - const needle = states.find((s) => s.id === villageId); - if (!needle) { - throw new VillageNotFound(`Village ${villageId} not found`); - } - return needle; + getVillageState(village: Village, storage: VillageStorage): VillageState { + return createVillageState(village, storage); } }