Simplify village state manipulation
This commit is contained in:
parent
9bbe3ff78d
commit
d03894c89d
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
},
|
||||
},
|
||||
|
@ -24,8 +24,8 @@ export class GrabberManager {
|
||||
}
|
||||
|
||||
private createGrabbers(): Array<Grabber> {
|
||||
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<Grabber> = [];
|
||||
grabbers.push(new VillageResourceGrabber(taskCollection, storage));
|
||||
grabbers.push(new VillageOverviewPageGrabber(taskCollection, storage));
|
||||
|
@ -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),
|
||||
];
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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([
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
|
@ -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<Village> {
|
||||
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<VillageState> {
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
createController(villageId: number): VillageController {
|
||||
const village = this.villageRepository.get(villageId);
|
||||
class IntVillageFactory {
|
||||
constructor(
|
||||
private readonly village: Village,
|
||||
private readonly stateFactory: VillageStateFactory
|
||||
) {}
|
||||
|
||||
short(): Village {
|
||||
return this.village;
|
||||
}
|
||||
|
||||
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()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,8 @@ import { VillageNotFound } from '../Errors';
|
||||
|
||||
export interface VillageRepositoryInterface {
|
||||
all(): Array<Village>;
|
||||
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');
|
||||
|
@ -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<Village>,
|
||||
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<Village>,
|
||||
storageFactory: VillageStorageFactory,
|
||||
taskCollectionFactory: VillageTaskCollectionFactory
|
||||
): Array<VillageState> {
|
||||
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<VillageState> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user