Improve hero balance action
This commit is contained in:
		@@ -1,10 +1,11 @@
 | 
			
		||||
import { Scheduler } from '../Scheduler';
 | 
			
		||||
import { ActionError, TryLaterError } from '../Errors';
 | 
			
		||||
import { AbortTaskError, TryLaterError } from '../Errors';
 | 
			
		||||
import { grabActiveVillageId } from '../Page/VillageBlock';
 | 
			
		||||
import { aroundMinutes } from '../utils';
 | 
			
		||||
import { Args } from '../Queue/Args';
 | 
			
		||||
import { Task } from '../Queue/TaskProvider';
 | 
			
		||||
import { VillageStorage } from '../Storage/VillageStorage';
 | 
			
		||||
import { VillageStateRepository } from '../VillageState';
 | 
			
		||||
 | 
			
		||||
const actionMap: { [name: string]: Function | undefined } = {};
 | 
			
		||||
 | 
			
		||||
@@ -12,29 +13,35 @@ export function registerAction(constructor: Function) {
 | 
			
		||||
    actionMap[constructor.name] = constructor;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function createActionHandler(name: string, scheduler: Scheduler): ActionController | undefined {
 | 
			
		||||
export function createActionHandler(
 | 
			
		||||
    name: string,
 | 
			
		||||
    scheduler: Scheduler,
 | 
			
		||||
    villageStateRepository: VillageStateRepository
 | 
			
		||||
): ActionController | undefined {
 | 
			
		||||
    const storedFunction = actionMap[name];
 | 
			
		||||
    if (storedFunction === undefined) {
 | 
			
		||||
        return undefined;
 | 
			
		||||
    }
 | 
			
		||||
    const constructor = (storedFunction as unknown) as typeof ActionController;
 | 
			
		||||
    return new constructor(scheduler);
 | 
			
		||||
    return new constructor(scheduler, villageStateRepository);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function err(msg: string): never {
 | 
			
		||||
    throw new ActionError(msg);
 | 
			
		||||
export function taskError(msg: string): never {
 | 
			
		||||
    throw new AbortTaskError(msg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class ActionController {
 | 
			
		||||
    protected scheduler: Scheduler;
 | 
			
		||||
    constructor(scheduler: Scheduler) {
 | 
			
		||||
    protected villageStateRepository: VillageStateRepository;
 | 
			
		||||
    constructor(scheduler: Scheduler, villageStateRepository: VillageStateRepository) {
 | 
			
		||||
        this.scheduler = scheduler;
 | 
			
		||||
        this.villageStateRepository = villageStateRepository;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async run(args: Args, task: Task) {}
 | 
			
		||||
 | 
			
		||||
    ensureSameVillage(args: Args, task: Task) {
 | 
			
		||||
        let villageId = args.villageId || err('Undefined village id');
 | 
			
		||||
        let villageId = args.villageId || taskError('Undefined village id');
 | 
			
		||||
        const activeVillageId = grabActiveVillageId();
 | 
			
		||||
        if (villageId !== activeVillageId) {
 | 
			
		||||
            throw new TryLaterError(aroundMinutes(1), 'Not same village');
 | 
			
		||||
 
 | 
			
		||||
@@ -1,15 +1,11 @@
 | 
			
		||||
import { ActionController, registerAction } from './ActionController';
 | 
			
		||||
import { grabVillageResources, grabVillageResourceStorage } from '../Page/ResourcesBlock';
 | 
			
		||||
import { changeHeroResource, grabCurrentHeroResource } from '../Page/HeroPage';
 | 
			
		||||
import { grabActiveVillageId, grabVillageList } from '../Page/VillageBlock';
 | 
			
		||||
import { grabActiveVillageId } from '../Page/VillageBlock';
 | 
			
		||||
import { HeroStorage } from '../Storage/HeroStorage';
 | 
			
		||||
import { calcHeroResource } from '../Core/HeroBalance';
 | 
			
		||||
import { HeroAllResources } from '../Core/Hero';
 | 
			
		||||
import { Args } from '../Queue/Args';
 | 
			
		||||
import { Task } from '../Queue/TaskProvider';
 | 
			
		||||
import { Resources } from '../Core/Resources';
 | 
			
		||||
import { createVillageStates } from '../VillageState';
 | 
			
		||||
import { ActionError } from '../Errors';
 | 
			
		||||
 | 
			
		||||
@registerAction
 | 
			
		||||
export class BalanceHeroResourcesAction extends ActionController {
 | 
			
		||||
@@ -22,13 +18,7 @@ export class BalanceHeroResourcesAction extends ActionController {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const villages = grabVillageList();
 | 
			
		||||
        const villageStates = createVillageStates(villages, this.scheduler);
 | 
			
		||||
        const thisVillageState = villageStates.find(s => s.id === thisVillageId);
 | 
			
		||||
 | 
			
		||||
        if (!thisVillageState) {
 | 
			
		||||
            throw new ActionError(`State for village ${thisVillageId} not found`);
 | 
			
		||||
        }
 | 
			
		||||
        const thisVillageState = this.villageStateRepository.getVillageState(thisVillageId);
 | 
			
		||||
 | 
			
		||||
        const requirements = [
 | 
			
		||||
            thisVillageState.required.balance,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
import { ActionController, err, registerAction } from './ActionController';
 | 
			
		||||
import { ActionController, taskError, registerAction } from './ActionController';
 | 
			
		||||
import { GrabError, TryLaterError } from '../Errors';
 | 
			
		||||
import { clickBuildButton } from '../Page/BuildingPage/BuildingPage';
 | 
			
		||||
import { aroundMinutes } from '../utils';
 | 
			
		||||
@@ -11,7 +11,7 @@ export class BuildBuildingAction extends ActionController {
 | 
			
		||||
        try {
 | 
			
		||||
            this.ensureSameVillage(args, task);
 | 
			
		||||
            this.ensureBuildingQueueIsEmpty();
 | 
			
		||||
            const buildTypeId = args.buildTypeId || err('Undefined build type id');
 | 
			
		||||
            const buildTypeId = args.buildTypeId || taskError('Undefined build type id');
 | 
			
		||||
            clickBuildButton(buildTypeId);
 | 
			
		||||
        } catch (e) {
 | 
			
		||||
            if (e instanceof GrabError) {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
import { ActionController, err, registerAction } from './ActionController';
 | 
			
		||||
import { ActionController, taskError, registerAction } from './ActionController';
 | 
			
		||||
import { GrabError, TryLaterError } from '../Errors';
 | 
			
		||||
import { aroundMinutes } from '../utils';
 | 
			
		||||
import { Args } from '../Queue/Args';
 | 
			
		||||
@@ -10,7 +10,7 @@ export class ForgeImprovementAction extends ActionController {
 | 
			
		||||
    async run(args: Args, task: Task): Promise<any> {
 | 
			
		||||
        try {
 | 
			
		||||
            this.ensureSameVillage(args, task);
 | 
			
		||||
            const unitId = args.unitId || err('No unitId in args');
 | 
			
		||||
            const unitId = args.unitId || taskError('No unitId in args');
 | 
			
		||||
            clickResearchButton(unitId);
 | 
			
		||||
        } catch (e) {
 | 
			
		||||
            if (e instanceof GrabError) {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
import { ActionController, err, registerAction } from './ActionController';
 | 
			
		||||
import { ActionController, taskError, registerAction } from './ActionController';
 | 
			
		||||
import { AbortTaskError, TryLaterError } from '../Errors';
 | 
			
		||||
import { Resources } from '../Core/Resources';
 | 
			
		||||
import { Coordinates, Village } from '../Core/Village';
 | 
			
		||||
@@ -15,7 +15,7 @@ const TIMEOUT = 15;
 | 
			
		||||
@registerAction
 | 
			
		||||
export class SendResourcesAction extends ActionController {
 | 
			
		||||
    async run(args: Args, task: Task): Promise<any> {
 | 
			
		||||
        const coordinates = Coordinates.fromObject(args.coordinates || err('No coordinates'));
 | 
			
		||||
        const coordinates = Coordinates.fromObject(args.coordinates || taskError('No coordinates'));
 | 
			
		||||
 | 
			
		||||
        const recipientVillage = args.targetVillageId
 | 
			
		||||
            ? this.findRecipientVillageById(args.targetVillageId)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
import { ActionController, err, registerAction } from './ActionController';
 | 
			
		||||
import { ActionController, taskError, registerAction } from './ActionController';
 | 
			
		||||
import { TryLaterError } from '../Errors';
 | 
			
		||||
import { aroundMinutes, randomInRange } from '../utils';
 | 
			
		||||
import { Args } from '../Queue/Args';
 | 
			
		||||
@@ -10,9 +10,9 @@ import { Resources } from '../Core/Resources';
 | 
			
		||||
@registerAction
 | 
			
		||||
export class TrainTrooperAction extends ActionController {
 | 
			
		||||
    async run(args: Args, task: Task): Promise<any> {
 | 
			
		||||
        const troopId = args.troopId || err('No troop id');
 | 
			
		||||
        const trainCount = args.trainCount || err('No troop train count');
 | 
			
		||||
        const troopResources = args.troopResources || err('No troop resources');
 | 
			
		||||
        const troopId = args.troopId || taskError('No troop id');
 | 
			
		||||
        const trainCount = args.trainCount || taskError('No troop train count');
 | 
			
		||||
        const troopResources = args.troopResources || taskError('No troop resources');
 | 
			
		||||
 | 
			
		||||
        const availableCount = getAvailableCount(troopId);
 | 
			
		||||
        const desiredCount = randomInRange(3, 12);
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,7 @@ import { DataStorageTaskProvider } from './Queue/DataStorageTaskProvider';
 | 
			
		||||
import { Statistics } from './Statistics';
 | 
			
		||||
import { StatisticsStorage } from './Storage/StatisticsStorage';
 | 
			
		||||
import { VillageRepository, VillageRepositoryInterface } from './VillageRepository';
 | 
			
		||||
import { VillageStateRepository } from './VillageState';
 | 
			
		||||
 | 
			
		||||
export class Container {
 | 
			
		||||
    private readonly version: string;
 | 
			
		||||
@@ -16,7 +17,7 @@ export class Container {
 | 
			
		||||
        this.version = version;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private _villageRepository: VillageRepositoryInterface | undefined;
 | 
			
		||||
    private _villageRepository: VillageRepository | undefined;
 | 
			
		||||
 | 
			
		||||
    get villageRepository(): VillageRepository {
 | 
			
		||||
        this._villageRepository =
 | 
			
		||||
@@ -27,6 +28,17 @@ export class Container {
 | 
			
		||||
        return this._villageRepository;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private _statistics: Statistics | undefined;
 | 
			
		||||
 | 
			
		||||
    get statistics(): Statistics {
 | 
			
		||||
        this._statistics =
 | 
			
		||||
            this._statistics ||
 | 
			
		||||
            (() => {
 | 
			
		||||
                return new Statistics(new StatisticsStorage());
 | 
			
		||||
            })();
 | 
			
		||||
        return this._statistics;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private _scheduler: Scheduler | undefined;
 | 
			
		||||
 | 
			
		||||
    get scheduler(): Scheduler {
 | 
			
		||||
@@ -41,13 +53,24 @@ export class Container {
 | 
			
		||||
        return this._scheduler;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private _villageStateRepository: VillageStateRepository | undefined;
 | 
			
		||||
 | 
			
		||||
    get villageStateRepository(): VillageStateRepository {
 | 
			
		||||
        this._villageStateRepository =
 | 
			
		||||
            this._villageStateRepository ||
 | 
			
		||||
            (() => {
 | 
			
		||||
                return new VillageStateRepository(this.villageRepository, this.scheduler);
 | 
			
		||||
            })();
 | 
			
		||||
        return this._villageStateRepository;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private _executor: Executor | undefined;
 | 
			
		||||
 | 
			
		||||
    get executor(): Executor {
 | 
			
		||||
        this._executor =
 | 
			
		||||
            this._executor ||
 | 
			
		||||
            (() => {
 | 
			
		||||
                return new Executor(this.version, this.scheduler, this.statistics);
 | 
			
		||||
                return new Executor(this.version, this.scheduler, this.villageStateRepository, this.statistics);
 | 
			
		||||
            })();
 | 
			
		||||
        return this._executor;
 | 
			
		||||
    }
 | 
			
		||||
@@ -58,19 +81,8 @@ export class Container {
 | 
			
		||||
        this._controlPanel =
 | 
			
		||||
            this._controlPanel ||
 | 
			
		||||
            (() => {
 | 
			
		||||
                return new ControlPanel(this.version, this.scheduler);
 | 
			
		||||
                return new ControlPanel(this.version, this.scheduler, this.villageStateRepository);
 | 
			
		||||
            })();
 | 
			
		||||
        return this._controlPanel;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private _statistics: Statistics | undefined;
 | 
			
		||||
 | 
			
		||||
    get statistics(): Statistics {
 | 
			
		||||
        this._statistics =
 | 
			
		||||
            this._statistics ||
 | 
			
		||||
            (() => {
 | 
			
		||||
                return new Statistics(new StatisticsStorage());
 | 
			
		||||
            })();
 | 
			
		||||
        return this._statistics;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@ import { notify, parseLocation, timestamp, uniqId, waitForLoad } from './utils';
 | 
			
		||||
import { Scheduler } from './Scheduler';
 | 
			
		||||
import { BuildingPageController } from './Page/BuildingPageController';
 | 
			
		||||
import { UpgradeBuildingTask } from './Task/UpgradeBuildingTask';
 | 
			
		||||
import { grabActiveVillageId, grabVillageList } from './Page/VillageBlock';
 | 
			
		||||
import { grabActiveVillageId } from './Page/VillageBlock';
 | 
			
		||||
import {
 | 
			
		||||
    grabResourceDeposits,
 | 
			
		||||
    onBuildingSlotCtrlClick,
 | 
			
		||||
@@ -17,7 +17,7 @@ import { ConsoleLogger, Logger } from './Logger';
 | 
			
		||||
import { DataStorage } from './DataStorage';
 | 
			
		||||
import { getBuildingPageAttributes, isBuildingPage } from './Page/PageDetectors';
 | 
			
		||||
import { ExecutionStorage } from './Storage/ExecutionStorage';
 | 
			
		||||
import { createVillageStates, VillageState } from './VillageState';
 | 
			
		||||
import { VillageState, VillageStateRepository } from './VillageState';
 | 
			
		||||
import { Task } from './Queue/TaskProvider';
 | 
			
		||||
import { Action } from './Queue/ActionQueue';
 | 
			
		||||
 | 
			
		||||
@@ -47,11 +47,13 @@ interface GameState {
 | 
			
		||||
export class ControlPanel {
 | 
			
		||||
    private readonly version: string;
 | 
			
		||||
    private readonly scheduler: Scheduler;
 | 
			
		||||
    private readonly villageStateRepository: VillageStateRepository;
 | 
			
		||||
    private readonly logger: Logger;
 | 
			
		||||
 | 
			
		||||
    constructor(version: string, scheduler: Scheduler) {
 | 
			
		||||
    constructor(version: string, scheduler: Scheduler, villageStateRepository: VillageStateRepository) {
 | 
			
		||||
        this.version = version;
 | 
			
		||||
        this.scheduler = scheduler;
 | 
			
		||||
        this.villageStateRepository = villageStateRepository;
 | 
			
		||||
        this.logger = new ConsoleLogger(this.constructor.name);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -64,6 +66,7 @@ export class ControlPanel {
 | 
			
		||||
        const villageId = grabActiveVillageId();
 | 
			
		||||
 | 
			
		||||
        const scheduler = this.scheduler;
 | 
			
		||||
        const villageStateRepository = this.villageStateRepository;
 | 
			
		||||
 | 
			
		||||
        const executionState = new ExecutionStorage();
 | 
			
		||||
 | 
			
		||||
@@ -91,7 +94,7 @@ export class ControlPanel {
 | 
			
		||||
            },
 | 
			
		||||
 | 
			
		||||
            refreshVillages() {
 | 
			
		||||
                this.villageStates = createVillageStates(grabVillageList(), scheduler);
 | 
			
		||||
                this.villageStates = villageStateRepository.getAllVillageStates();
 | 
			
		||||
                for (let state of this.villageStates) {
 | 
			
		||||
                    if (state.village.active) {
 | 
			
		||||
                        this.activeVillageState = state;
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,13 @@ export class GrabError extends Error {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class VillageNotFound extends Error {
 | 
			
		||||
    constructor(msg: string = '') {
 | 
			
		||||
        super(msg);
 | 
			
		||||
        Object.setPrototypeOf(this, VillageNotFound.prototype);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class ActionError extends Error {
 | 
			
		||||
    constructor(msg: string = '') {
 | 
			
		||||
        super(msg);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
import { markPage, sleepMicro, timestamp, waitForLoad } from './utils';
 | 
			
		||||
import { AbortTaskError, ActionError, GrabError, TryLaterError } from './Errors';
 | 
			
		||||
import { AbortTaskError, ActionError, GrabError, TryLaterError, VillageNotFound } from './Errors';
 | 
			
		||||
import { TaskQueueRenderer } from './TaskQueueRenderer';
 | 
			
		||||
import { createActionHandler } from './Action/ActionController';
 | 
			
		||||
import { ConsoleLogger, Logger } from './Logger';
 | 
			
		||||
@@ -10,6 +10,7 @@ import { ExecutionStorage } from './Storage/ExecutionStorage';
 | 
			
		||||
import { Action } from './Queue/ActionQueue';
 | 
			
		||||
import { Task } from './Queue/TaskProvider';
 | 
			
		||||
import { createTaskHandler } from './Task/TaskMap';
 | 
			
		||||
import { VillageStateRepository } from './VillageState';
 | 
			
		||||
 | 
			
		||||
export interface ExecutionSettings {
 | 
			
		||||
    pauseTs: number;
 | 
			
		||||
@@ -18,14 +19,21 @@ export interface ExecutionSettings {
 | 
			
		||||
export class Executor {
 | 
			
		||||
    private readonly version: string;
 | 
			
		||||
    private readonly scheduler: Scheduler;
 | 
			
		||||
    private readonly villageStateRepository: VillageStateRepository;
 | 
			
		||||
    private grabbers: GrabberManager;
 | 
			
		||||
    private statistics: Statistics;
 | 
			
		||||
    private executionState: ExecutionStorage;
 | 
			
		||||
    private logger: Logger;
 | 
			
		||||
 | 
			
		||||
    constructor(version: string, scheduler: Scheduler, statistics: Statistics) {
 | 
			
		||||
    constructor(
 | 
			
		||||
        version: string,
 | 
			
		||||
        scheduler: Scheduler,
 | 
			
		||||
        villageStateRepository: VillageStateRepository,
 | 
			
		||||
        statistics: Statistics
 | 
			
		||||
    ) {
 | 
			
		||||
        this.version = version;
 | 
			
		||||
        this.scheduler = scheduler;
 | 
			
		||||
        this.villageStateRepository = villageStateRepository;
 | 
			
		||||
        this.grabbers = new GrabberManager(scheduler);
 | 
			
		||||
        this.statistics = statistics;
 | 
			
		||||
        this.executionState = new ExecutionStorage();
 | 
			
		||||
@@ -97,7 +105,7 @@ export class Executor {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private async processActionCommand(cmd: Action, task: Task) {
 | 
			
		||||
        const actionHandler = createActionHandler(cmd.name, this.scheduler);
 | 
			
		||||
        const actionHandler = createActionHandler(cmd.name, this.scheduler, this.villageStateRepository);
 | 
			
		||||
        this.logger.info('PROCESS ACTION', cmd.name, actionHandler);
 | 
			
		||||
        if (cmd.args.taskId !== task.id) {
 | 
			
		||||
            throw new ActionError(`Action task id ${cmd.args.taskId} not equal current task id ${task.id}`);
 | 
			
		||||
@@ -125,24 +133,30 @@ export class Executor {
 | 
			
		||||
        this.scheduler.clearActions();
 | 
			
		||||
 | 
			
		||||
        if (err instanceof AbortTaskError) {
 | 
			
		||||
            this.logger.warn('ABORT TASK', task.id, 'MSG', err.message);
 | 
			
		||||
            this.logger.warn('Abort task', task.id, 'MSG', err.message);
 | 
			
		||||
            this.scheduler.removeTask(task.id);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (err instanceof VillageNotFound) {
 | 
			
		||||
            this.logger.error('Village not found, abort task', task.id, 'msg', err.message);
 | 
			
		||||
            this.scheduler.removeTask(task.id);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (err instanceof TryLaterError) {
 | 
			
		||||
            this.logger.warn('TRY', task.id, 'AFTER', err.seconds, 'MSG', err.message);
 | 
			
		||||
            this.logger.warn('Try', task.id, 'after', err.seconds, 'msg', err.message);
 | 
			
		||||
            this.scheduler.postponeTask(task.id, err.seconds);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (err instanceof ActionError) {
 | 
			
		||||
            this.logger.error('ACTION ABORTED', err.message);
 | 
			
		||||
        if (err instanceof GrabError) {
 | 
			
		||||
            this.logger.error('Layout element not found, abort action', err.message);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (err instanceof GrabError) {
 | 
			
		||||
            this.logger.error('ELEMENT NOT FOUND, ACTION ABORTED', err.message);
 | 
			
		||||
        if (err instanceof ActionError) {
 | 
			
		||||
            this.logger.error('Abort action', err.message);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,8 @@ import { Scheduler } from './Scheduler';
 | 
			
		||||
import { Resources } from './Core/Resources';
 | 
			
		||||
import { VillageStorage } from './Storage/VillageStorage';
 | 
			
		||||
import { calcGatheringTimings, GatheringTime } from './Core/GatheringTimings';
 | 
			
		||||
import { VillageRepositoryInterface } from './VillageRepository';
 | 
			
		||||
import { VillageNotFound } from './Errors';
 | 
			
		||||
 | 
			
		||||
interface StorageBalance {
 | 
			
		||||
    resources: Resources;
 | 
			
		||||
@@ -127,7 +129,30 @@ function createVillageState(
 | 
			
		||||
    return { ...state, commitments, shipment: villageIds };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function createVillageStates(villages: Array<Village>, scheduler: Scheduler): Array<VillageState> {
 | 
			
		||||
function getVillageStates(villages: Array<Village>, scheduler: Scheduler): Array<VillageState> {
 | 
			
		||||
    const ownStates = createVillageOwnStates(villages, scheduler);
 | 
			
		||||
    return villages.map(village => createVillageState(ownStates[village.id], ownStates, scheduler));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class VillageStateRepository {
 | 
			
		||||
    private villageRepository: VillageRepositoryInterface;
 | 
			
		||||
    private scheduler: Scheduler;
 | 
			
		||||
 | 
			
		||||
    constructor(villageRepository: VillageRepositoryInterface, scheduler: Scheduler) {
 | 
			
		||||
        this.villageRepository = villageRepository;
 | 
			
		||||
        this.scheduler = scheduler;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    getAllVillageStates(): Array<VillageState> {
 | 
			
		||||
        return getVillageStates(this.villageRepository.all(), this.scheduler);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    getVillageState(villageId: number): VillageState {
 | 
			
		||||
        const states = getVillageStates(this.villageRepository.all(), this.scheduler);
 | 
			
		||||
        const needle = states.find(s => s.id === villageId);
 | 
			
		||||
        if (!needle) {
 | 
			
		||||
            throw new VillageNotFound(`Village ${villageId} not found`);
 | 
			
		||||
        }
 | 
			
		||||
        return needle;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user