diff --git a/src/Action/ActionController.ts b/src/Action/ActionController.ts
index 7c3026c..bcefabe 100644
--- a/src/Action/ActionController.ts
+++ b/src/Action/ActionController.ts
@@ -5,7 +5,7 @@ import { aroundMinutes } from '../utils';
 import { Args } from '../Queue/Args';
 import { Task } from '../Queue/TaskProvider';
 import { VillageStorage } from '../Storage/VillageStorage';
-import { VillageStateRepository } from '../VillageState';
+import { VillageFactory } from '../VillageFactory';
 
 const actionMap: { [name: string]: Function | undefined } = {};
 
@@ -16,22 +16,22 @@ export function registerAction(constructor: Function) {
 export function createActionHandler(
     name: string,
     scheduler: Scheduler,
-    villageStateRepository: VillageStateRepository
+    villageFactory: VillageFactory
 ): ActionController | undefined {
     const storedFunction = actionMap[name];
     if (storedFunction === undefined) {
         return undefined;
     }
     const constructor = (storedFunction as unknown) as typeof ActionController;
-    return new constructor(scheduler, villageStateRepository);
+    return new constructor(scheduler, villageFactory);
 }
 
 export class ActionController {
-    protected scheduler: Scheduler;
-    protected villageStateRepository: VillageStateRepository;
-    constructor(scheduler: Scheduler, villageStateRepository: VillageStateRepository) {
+    protected readonly scheduler: Scheduler;
+    protected readonly villageFactory: VillageFactory;
+    constructor(scheduler: Scheduler, villageFactory: VillageFactory) {
         this.scheduler = scheduler;
-        this.villageStateRepository = villageStateRepository;
+        this.villageFactory = villageFactory;
     }
 
     async run(args: Args, task: Task) {}
diff --git a/src/Action/BalanceHeroResourcesAction.ts b/src/Action/BalanceHeroResourcesAction.ts
index 7a19520..7682312 100644
--- a/src/Action/BalanceHeroResourcesAction.ts
+++ b/src/Action/BalanceHeroResourcesAction.ts
@@ -18,7 +18,7 @@ export class BalanceHeroResourcesAction extends ActionController {
             return;
         }
 
-        const thisVillageState = this.villageStateRepository.getVillageState(thisVillageId);
+        const thisVillageState = this.villageFactory.createState(thisVillageId);
 
         const requirements = [
             thisVillageState.required.balance,
diff --git a/src/Action/ClickButtonAction.ts b/src/Action/ClickButtonAction.ts
index 494711c..ef616e0 100644
--- a/src/Action/ClickButtonAction.ts
+++ b/src/Action/ClickButtonAction.ts
@@ -1,5 +1,5 @@
 import { ActionController, registerAction } from './ActionController';
-import { AbortTaskError, taskError } from '../Errors';
+import { taskError } from '../Errors';
 import { Args } from '../Queue/Args';
 import { Task } from '../Queue/TaskProvider';
 
diff --git a/src/Action/SendResourcesAction.ts b/src/Action/SendResourcesAction.ts
index e54dabd..e782de5 100644
--- a/src/Action/SendResourcesAction.ts
+++ b/src/Action/SendResourcesAction.ts
@@ -18,8 +18,8 @@ export class SendResourcesAction extends ActionController {
 
         const coordinates = Coordinates.fromObject(args.coordinates || taskError('No coordinates'));
 
-        const senderVillage = this.villageStateRepository.getVillageState(senderVillageId);
-        const recipientVillage = this.villageStateRepository.getVillageState(targetVillageId);
+        const senderVillage = this.villageFactory.createState(senderVillageId);
+        const recipientVillage = this.villageFactory.createState(targetVillageId);
 
         const readyToTransfer = this.getResourcesForTransfer(senderVillage, recipientVillage);
 
diff --git a/src/Action/UpgradeResourceToLevel.ts b/src/Action/UpgradeResourceToLevel.ts
index 4a1a6d5..09aa7e0 100644
--- a/src/Action/UpgradeResourceToLevel.ts
+++ b/src/Action/UpgradeResourceToLevel.ts
@@ -1,5 +1,5 @@
 import { ActionController, registerAction } from './ActionController';
-import { AbortTaskError, ActionError, taskError, TryLaterError } from '../Errors';
+import { ActionError, taskError, TryLaterError } from '../Errors';
 import { grabResourceDeposits } from '../Page/SlotBlock';
 import { UpgradeBuildingTask } from '../Task/UpgradeBuildingTask';
 import { ResourceDeposit } from '../Game';
diff --git a/src/Container.ts b/src/Container.ts
index 06de00e..7f22ee6 100644
--- a/src/Container.ts
+++ b/src/Container.ts
@@ -8,9 +8,8 @@ import { DataStorageTaskProvider } from './Queue/DataStorageTaskProvider';
 import { Statistics } from './Statistics';
 import { StatisticsStorage } from './Storage/StatisticsStorage';
 import { VillageRepository } from './VillageRepository';
-import { VillageStateRepository } from './VillageState';
 import { LogStorage } from './Storage/LogStorage';
-import { VillageControllerFactory } from './VillageControllerFactory';
+import { VillageFactory } from './VillageFactory';
 import { GrabberManager } from './Grabber/GrabberManager';
 
 export class Container {
@@ -42,15 +41,15 @@ export class Container {
         return this._statistics;
     }
 
-    private _villageControllerFactory: VillageControllerFactory | undefined;
+    private _villageFactory: VillageFactory | undefined;
 
-    get villageControllerFactory(): VillageControllerFactory {
-        this._villageControllerFactory =
-            this._villageControllerFactory ||
+    get villageFactory(): VillageFactory {
+        this._villageFactory =
+            this._villageFactory ||
             (() => {
-                return new VillageControllerFactory(this.villageRepository);
+                return new VillageFactory(this.villageRepository);
             })();
-        return this._villageControllerFactory;
+        return this._villageFactory;
     }
 
     private _scheduler: Scheduler | undefined;
@@ -68,31 +67,20 @@ export class Container {
                     taskQueue,
                     actionQueue,
                     this.villageRepository,
-                    this.villageControllerFactory,
+                    this.villageFactory,
                     new ConsoleLogger(Scheduler.name)
                 );
             })();
         return this._scheduler;
     }
 
-    private _villageStateRepository: VillageStateRepository | undefined;
-
-    get villageStateRepository(): VillageStateRepository {
-        this._villageStateRepository =
-            this._villageStateRepository ||
-            (() => {
-                return new VillageStateRepository(this.villageRepository, this.villageControllerFactory);
-            })();
-        return this._villageStateRepository;
-    }
-
     private _grabberManager: GrabberManager | undefined;
 
     get grabberManager(): GrabberManager {
         this._grabberManager =
             this._grabberManager ||
             (() => {
-                return new GrabberManager(this.villageControllerFactory);
+                return new GrabberManager(this.villageFactory);
             })();
         return this._grabberManager;
     }
@@ -110,8 +98,7 @@ export class Container {
                 return new Executor(
                     this.version,
                     this.scheduler,
-                    this.villageStateRepository,
-                    this.villageControllerFactory,
+                    this.villageFactory,
                     this.grabberManager,
                     this.statistics,
                     logger
@@ -126,12 +113,7 @@ export class Container {
         this._controlPanel =
             this._controlPanel ||
             (() => {
-                return new ControlPanel(
-                    this.version,
-                    this.scheduler,
-                    this.villageStateRepository,
-                    this.villageControllerFactory
-                );
+                return new ControlPanel(this.version, this.scheduler, this.villageFactory);
             })();
         return this._controlPanel;
     }
diff --git a/src/ControlPanel.ts b/src/ControlPanel.ts
index 93347bb..7efdedd 100644
--- a/src/ControlPanel.ts
+++ b/src/ControlPanel.ts
@@ -18,11 +18,11 @@ import { ConsoleLogger, Logger } from './Logger';
 import { DataStorage } from './DataStorage';
 import { getBuildingPageAttributes, isBuildingPage } from './Page/PageDetectors';
 import { ExecutionStorage } from './Storage/ExecutionStorage';
-import { VillageState, VillageStateRepository } from './VillageState';
+import { VillageState } from './VillageState';
 import { Task } from './Queue/TaskProvider';
 import { Action } from './Queue/ActionQueue';
 import { createStore } from './DashboardView/Store';
-import { VillageControllerFactory } from './VillageControllerFactory';
+import { VillageFactory } from './VillageFactory';
 
 Vue.use(Vuex);
 
@@ -52,20 +52,13 @@ interface GameState {
 export class ControlPanel {
     private readonly version: string;
     private readonly scheduler: Scheduler;
-    private readonly villageStateRepository: VillageStateRepository;
     private readonly logger: Logger;
-    private villageControllerFactory: VillageControllerFactory;
+    private readonly villageFactory: VillageFactory;
 
-    constructor(
-        version: string,
-        scheduler: Scheduler,
-        villageStateRepository: VillageStateRepository,
-        villageControllerFactory: VillageControllerFactory
-    ) {
+    constructor(version: string, scheduler: Scheduler, villageFactory: VillageFactory) {
         this.version = version;
         this.scheduler = scheduler;
-        this.villageStateRepository = villageStateRepository;
-        this.villageControllerFactory = villageControllerFactory;
+        this.villageFactory = villageFactory;
         this.logger = new ConsoleLogger(this.constructor.name);
     }
 
@@ -78,7 +71,7 @@ export class ControlPanel {
         const villageId = grabActiveVillageId();
 
         const scheduler = this.scheduler;
-        const villageStateRepository = this.villageStateRepository;
+        const villageFactory = this.villageFactory;
 
         const executionState = new ExecutionStorage();
 
@@ -106,7 +99,7 @@ export class ControlPanel {
             },
 
             refreshVillages() {
-                this.villageStates = villageStateRepository.getAllVillageStates();
+                this.villageStates = villageFactory.getAllVillageStates();
                 for (let state of this.villageStates) {
                     if (state.village.active) {
                         this.activeVillageState = state;
@@ -136,8 +129,8 @@ export class ControlPanel {
         DataStorage.onChange(() => state.refresh());
 
         const getBuildingsInQueue = () =>
-            this.villageControllerFactory
-                .create(villageId)
+            this.villageFactory
+                .createTaskCollection(villageId)
                 .getTasks()
                 .filter(t => t.name === UpgradeBuildingTask.name)
                 .map(t => t.args.buildId || 0);
@@ -163,21 +156,21 @@ export class ControlPanel {
             const buildPage = new BuildingPageController(
                 this.scheduler,
                 getBuildingPageAttributes(),
-                this.villageControllerFactory.create(villageId)
+                this.villageFactory.createController(villageId)
             );
             buildPage.run();
         }
 
-        this.createControlPanel(state, villageStateRepository);
+        this.createControlPanel(state, villageFactory);
     }
 
-    private createControlPanel(gameState: GameState, villageStateRepository: VillageStateRepository) {
+    private createControlPanel(gameState: GameState, villageFactory: VillageFactory) {
         const appId = `app-${uniqId()}`;
         jQuery('body').prepend(`<div id="${appId}"></div>`);
         new Vue({
             el: `#${appId}`,
             data: gameState,
-            store: createStore(villageStateRepository),
+            store: createStore(villageFactory),
             render: h => h(DashboardApp),
         });
     }
diff --git a/src/DashboardView/Store.ts b/src/DashboardView/Store.ts
index 932b774..cccf914 100644
--- a/src/DashboardView/Store.ts
+++ b/src/DashboardView/Store.ts
@@ -1,9 +1,9 @@
 import Vuex from 'vuex';
 import { LogStorage } from '../Storage/LogStorage';
-import { VillageStateRepository } from '../VillageState';
 import { VillageSettings, VillageSettingsDefaults } from '../Core/Village';
 import { getNumber, notify } from '../utils';
 import { VillageStorage } from '../Storage/VillageStorage';
+import { VillageFactory } from '../VillageFactory';
 
 export enum Mutations {
     showLogs = 'showLogs',
@@ -22,7 +22,7 @@ export enum Actions {
     SaveVillageSettings = 'save_village_settings',
 }
 
-export function createStore(villageStateRepository: VillageStateRepository) {
+export function createStore(villageFactory: VillageFactory) {
     const store = new Vuex.Store({
         state: {
             views: {
@@ -74,7 +74,7 @@ export function createStore(villageStateRepository: VillageStateRepository) {
         },
         actions: {
             [Actions.OpenVillageEditor]({ commit }, { villageId }) {
-                const state = villageStateRepository.getVillageState(villageId);
+                const state = villageFactory.createState(villageId);
                 const settings = state.settings;
                 commit(Mutations.SetVillageSettings, {
                     villageId: state.id,
diff --git a/src/Executor.ts b/src/Executor.ts
index 923cd52..a4fbf5b 100644
--- a/src/Executor.ts
+++ b/src/Executor.ts
@@ -10,8 +10,8 @@ import { ExecutionStorage } from './Storage/ExecutionStorage';
 import { Action } from './Queue/ActionQueue';
 import { Task } from './Queue/TaskProvider';
 import { createTaskHandler } from './Task/TaskMap';
-import { VillageStateRepository } from './VillageState';
-import { VillageControllerFactory } from './VillageControllerFactory';
+import { VillageStateFactory } from './VillageState';
+import { VillageFactory } from './VillageFactory';
 
 export interface ExecutionSettings {
     pauseTs: number;
@@ -20,8 +20,7 @@ export interface ExecutionSettings {
 export class Executor {
     private readonly version: string;
     private readonly scheduler: Scheduler;
-    private readonly villageStateRepository: VillageStateRepository;
-    private villageControllerFactory: VillageControllerFactory;
+    private villageFactory: VillageFactory;
     private grabberManager: GrabberManager;
     private statistics: Statistics;
     private executionState: ExecutionStorage;
@@ -30,16 +29,14 @@ export class Executor {
     constructor(
         version: string,
         scheduler: Scheduler,
-        villageStateRepository: VillageStateRepository,
-        villageControllerFactory: VillageControllerFactory,
+        villageFactory: VillageFactory,
         grabberManager: GrabberManager,
         statistics: Statistics,
         logger: Logger
     ) {
         this.version = version;
         this.scheduler = scheduler;
-        this.villageStateRepository = villageStateRepository;
-        this.villageControllerFactory = villageControllerFactory;
+        this.villageFactory = villageFactory;
         this.grabberManager = grabberManager;
         this.statistics = statistics;
         this.executionState = new ExecutionStorage();
@@ -109,7 +106,7 @@ export class Executor {
     }
 
     private async processActionCommand(action: Action, task: Task) {
-        const actionHandler = createActionHandler(action.name, this.scheduler, this.villageStateRepository);
+        const actionHandler = createActionHandler(action.name, this.scheduler, this.villageFactory);
         this.logger.info('Process action', action.name, actionHandler);
         if (actionHandler) {
             this.statistics.incrementAction(timestamp());
diff --git a/src/Grabber/BuildingContractGrabber.ts b/src/Grabber/BuildingContractGrabber.ts
index 8228c52..a24b91b 100644
--- a/src/Grabber/BuildingContractGrabber.ts
+++ b/src/Grabber/BuildingContractGrabber.ts
@@ -20,7 +20,7 @@ export class BuildingContractGrabber extends Grabber {
 
         const contract = grabContractResources();
 
-        this.controller.updateResources(contract, {
+        this.taskCollection.updateResources(contract, {
             type: ContractType.UpgradeBuilding,
             buildId: building.buildId,
         });
diff --git a/src/Grabber/ForgePageGrabber.ts b/src/Grabber/ForgePageGrabber.ts
index 131db7c..c5836a4 100644
--- a/src/Grabber/ForgePageGrabber.ts
+++ b/src/Grabber/ForgePageGrabber.ts
@@ -20,7 +20,7 @@ export class ForgePageGrabber extends Grabber {
         const contracts = grabImprovementContracts();
 
         for (let { resources, unitId } of contracts) {
-            this.controller.updateResources(resources, {
+            this.taskCollection.updateResources(resources, {
                 type: ContractType.ImproveTrooper,
                 buildId,
                 unitId,
@@ -29,8 +29,7 @@ export class ForgePageGrabber extends Grabber {
     }
 
     private grabTimer(): void {
-        const storage = this.controller.getStorage();
         const seconds = grabRemainingSeconds();
-        storage.storeQueueTaskEnding(ProductionQueue.UpgradeUnit, seconds ? seconds + timestamp() : 0);
+        this.storage.storeQueueTaskEnding(ProductionQueue.UpgradeUnit, seconds ? seconds + timestamp() : 0);
     }
 }
diff --git a/src/Grabber/Grabber.ts b/src/Grabber/Grabber.ts
index db0adc1..8919e93 100644
--- a/src/Grabber/Grabber.ts
+++ b/src/Grabber/Grabber.ts
@@ -1,10 +1,13 @@
-import { VillageController } from '../VillageController';
+import { VillageTaskCollection } from '../VillageTaskCollection';
+import { VillageStorage } from '../Storage/VillageStorage';
 
 export abstract class Grabber {
-    protected controller: VillageController;
+    protected taskCollection: VillageTaskCollection;
+    protected storage: VillageStorage;
 
-    constructor(controller: VillageController) {
-        this.controller = controller;
+    constructor(taskCollection: VillageTaskCollection, storage: VillageStorage) {
+        this.taskCollection = taskCollection;
+        this.storage = storage;
     }
 
     abstract grab(): void;
diff --git a/src/Grabber/GrabberManager.ts b/src/Grabber/GrabberManager.ts
index 0b9632d..ac272ff 100644
--- a/src/Grabber/GrabberManager.ts
+++ b/src/Grabber/GrabberManager.ts
@@ -6,12 +6,12 @@ import { MarketPageGrabber } from './MarketPageGrabber';
 import { BuildingContractGrabber } from './BuildingContractGrabber';
 import { ForgePageGrabber } from './ForgePageGrabber';
 import { GuildHallPageGrabber } from './GuildHallPageGrabber';
-import { VillageControllerFactory } from '../VillageControllerFactory';
+import { VillageFactory } from '../VillageFactory';
 
 export class GrabberManager {
-    private factory: VillageControllerFactory;
+    private factory: VillageFactory;
 
-    constructor(factory: VillageControllerFactory) {
+    constructor(factory: VillageFactory) {
         this.factory = factory;
     }
 
@@ -23,15 +23,16 @@ export class GrabberManager {
     }
 
     private createGrabbers(): Array<Grabber> {
-        const controller = this.factory.getActive();
+        const storage = this.factory.createStorageForActiveVillage();
+        const taskCollection = this.factory.createTaskCollectionForActiveVillage();
         const grabbers: Array<Grabber> = [];
-        grabbers.push(new VillageResourceGrabber(controller));
-        grabbers.push(new VillageOverviewPageGrabber(controller));
-        grabbers.push(new HeroPageGrabber(controller));
-        grabbers.push(new MarketPageGrabber(controller));
-        grabbers.push(new BuildingContractGrabber(controller));
-        grabbers.push(new ForgePageGrabber(controller));
-        grabbers.push(new GuildHallPageGrabber(controller));
+        grabbers.push(new VillageResourceGrabber(taskCollection, storage));
+        grabbers.push(new VillageOverviewPageGrabber(taskCollection, storage));
+        grabbers.push(new HeroPageGrabber(taskCollection, storage));
+        grabbers.push(new MarketPageGrabber(taskCollection, storage));
+        grabbers.push(new BuildingContractGrabber(taskCollection, storage));
+        grabbers.push(new ForgePageGrabber(taskCollection, storage));
+        grabbers.push(new GuildHallPageGrabber(taskCollection, storage));
         return grabbers;
     }
 }
diff --git a/src/Grabber/GuildHallPageGrabber.ts b/src/Grabber/GuildHallPageGrabber.ts
index e11fa05..60663d8 100644
--- a/src/Grabber/GuildHallPageGrabber.ts
+++ b/src/Grabber/GuildHallPageGrabber.ts
@@ -11,7 +11,6 @@ export class GuildHallPageGrabber extends Grabber {
         }
 
         const seconds = grabRemainingSeconds();
-        const storage = this.controller.getStorage();
-        storage.storeQueueTaskEnding(ProductionQueue.Celebration, seconds ? seconds + timestamp() : 0);
+        this.storage.storeQueueTaskEnding(ProductionQueue.Celebration, seconds ? seconds + timestamp() : 0);
     }
 }
diff --git a/src/Grabber/MarketPageGrabber.ts b/src/Grabber/MarketPageGrabber.ts
index 973cab5..7d000f9 100644
--- a/src/Grabber/MarketPageGrabber.ts
+++ b/src/Grabber/MarketPageGrabber.ts
@@ -8,7 +8,6 @@ export class MarketPageGrabber extends Grabber {
             return;
         }
 
-        const storage = this.controller.getStorage();
-        storage.storeIncomingMerchants(grabIncomingMerchants());
+        this.storage.storeIncomingMerchants(grabIncomingMerchants());
     }
 }
diff --git a/src/Grabber/VillageOverviewPageGrabber.ts b/src/Grabber/VillageOverviewPageGrabber.ts
index d9d18ed..ee1ebb4 100644
--- a/src/Grabber/VillageOverviewPageGrabber.ts
+++ b/src/Grabber/VillageOverviewPageGrabber.ts
@@ -12,13 +12,12 @@ export class VillageOverviewPageGrabber extends Grabber {
             return;
         }
 
-        const storage = this.controller.getStorage();
-        storage.storeResourcesPerformance(grabResourcesPerformance());
-        storage.storeBuildingQueueInfo(this.grabBuildingQueueInfoOrDefault());
+        this.storage.storeResourcesPerformance(grabResourcesPerformance());
+        this.storage.storeBuildingQueueInfo(this.grabBuildingQueueInfoOrDefault());
 
         const buildingQueueInfo = this.grabBuildingQueueInfoOrDefault();
         const buildingEndTime = buildingQueueInfo.seconds ? buildingQueueInfo.seconds + timestamp() : 0;
-        storage.storeQueueTaskEnding(ProductionQueue.Building, buildingEndTime);
+        this.storage.storeQueueTaskEnding(ProductionQueue.Building, buildingEndTime);
     }
 
     private grabBuildingQueueInfoOrDefault() {
diff --git a/src/Grabber/VillageResourceGrabber.ts b/src/Grabber/VillageResourceGrabber.ts
index 5fa6f81..7f88ead 100644
--- a/src/Grabber/VillageResourceGrabber.ts
+++ b/src/Grabber/VillageResourceGrabber.ts
@@ -3,8 +3,7 @@ import { grabVillageResources, grabVillageResourceStorage } from '../Page/Resour
 
 export class VillageResourceGrabber extends Grabber {
     grab(): void {
-        const storage = this.controller.getStorage();
-        storage.storeResources(grabVillageResources());
-        storage.storeResourceStorage(grabVillageResourceStorage());
+        this.storage.storeResources(grabVillageResources());
+        this.storage.storeResourceStorage(grabVillageResourceStorage());
     }
 }
diff --git a/src/Scheduler.ts b/src/Scheduler.ts
index efb977b..0b36091 100644
--- a/src/Scheduler.ts
+++ b/src/Scheduler.ts
@@ -12,8 +12,9 @@ import { ImmutableTaskList, Task, TaskId, uniqTaskId, withTime } from './Queue/T
 import { MARKET_ID } from './Core/Buildings';
 import { VillageRepositoryInterface } from './VillageRepository';
 import { isProductionTask } from './Core/ProductionQueue';
-import { VillageControllerFactory } from './VillageControllerFactory';
+import { VillageFactory } from './VillageFactory';
 import { RunVillageProductionTask } from './Task/RunVillageProductionTask';
+import { VillageNotFound } from './Errors';
 
 export interface NextExecution {
     task?: Task;
@@ -24,14 +25,14 @@ export class Scheduler {
     private taskQueue: TaskQueue;
     private actionQueue: ActionQueue;
     private villageRepository: VillageRepositoryInterface;
-    private villageControllerFactory: VillageControllerFactory;
+    private villageControllerFactory: VillageFactory;
     private logger: Logger;
 
     constructor(
         taskQueue: TaskQueue,
         actionQueue: ActionQueue,
         villageRepository: VillageRepositoryInterface,
-        villageControllerFactory: VillageControllerFactory,
+        villageControllerFactory: VillageFactory,
         logger: Logger
     ) {
         this.taskQueue = taskQueue;
@@ -96,13 +97,13 @@ export class Scheduler {
     private replaceTask(task: Task): Task | undefined {
         if (task.name === RunVillageProductionTask.name && task.args.villageId) {
             const villageId = task.args.villageId;
-            const controller = this.villageControllerFactory.create(villageId);
+            const controller = this.villageControllerFactory.createController(villageId);
             const villageTask = controller.getReadyProductionTask();
             if (villageTask) {
                 this.removeTask(task.id);
                 const newTask = new Task(villageTask.id, 0, villageTask.name, {
                     ...villageTask.args,
-                    villageId: controller.villageId,
+                    villageId: controller.getVillageId(),
                 });
                 this.taskQueue.add(newTask);
                 return newTask;
@@ -113,7 +114,7 @@ export class Scheduler {
 
     scheduleTask(name: string, args: Args, ts?: number | undefined): void {
         if (isProductionTask(name) && args.villageId) {
-            const controller = this.villageControllerFactory.create(args.villageId);
+            const controller = this.villageControllerFactory.createController(args.villageId);
             controller.addTask(name, args);
         } else {
             this.logger.info('Schedule task', name, args, ts);
@@ -143,7 +144,7 @@ export class Scheduler {
         const task = this.taskQueue.findById(taskId);
         const villageId = task ? task.args.villageId : undefined;
         if (villageId) {
-            const controller = this.villageControllerFactory.create(villageId);
+            const controller = this.villageControllerFactory.createController(villageId);
             controller.removeTask(taskId);
         }
         this.removeTask(taskId);
@@ -156,7 +157,7 @@ export class Scheduler {
         }
 
         if (isProductionTask(task.name) && task.args.villageId) {
-            const controller = this.villageControllerFactory.create(task.args.villageId);
+            const controller = this.villageControllerFactory.createController(task.args.villageId);
             controller.postponeTask(taskId, seconds);
             this.removeTask(taskId);
         } else {
@@ -186,7 +187,7 @@ export class Scheduler {
         this.dropResourceTransferTasks(fromVillageId, toVillageId);
         const village = this.villageRepository.all().find(v => v.id === toVillageId);
         if (!village) {
-            throw new Error('No village');
+            throw new VillageNotFound(`Village ${toVillageId} not found`);
         }
         this.scheduleTask(SendResourcesTask.name, {
             villageId: fromVillageId,
diff --git a/src/Storage/LogStorage.ts b/src/Storage/LogStorage.ts
index 95fc124..881b76d 100644
--- a/src/Storage/LogStorage.ts
+++ b/src/Storage/LogStorage.ts
@@ -1,5 +1,4 @@
 import { DataStorage } from '../DataStorage';
-import { ActionStatistics, StatisticsStorageInterface } from '../Statistics';
 import { LogStorageInterface, StorageLogRecord } from '../Logger';
 
 const NAMESPACE = 'logs.v1';
diff --git a/src/Storage/VillageStorage.ts b/src/Storage/VillageStorage.ts
index 0a9e4ed..3c7fd89 100644
--- a/src/Storage/VillageStorage.ts
+++ b/src/Storage/VillageStorage.ts
@@ -112,41 +112,7 @@ export class VillageStorage {
         });
     }
 
-    addTask(task: Task): void {
-        const tasks = this.getTasks();
-        tasks.push(task);
-        this.storeTaskList(tasks);
-    }
-
-    modifyTasks(predicate: (t: Task) => boolean, modifier: (t: Task) => Task): number {
-        const [matched, other] = this.split(predicate);
-        const modified = matched.map(modifier);
-        const modifiedCount = modified.length;
-        this.storeTaskList(modified.concat(other));
-        return modifiedCount;
-    }
-
-    removeTasks(predicate: (t: Task) => boolean): number {
-        const [_, other] = this.split(predicate);
-        const result = other.length;
-        this.storeTaskList(other);
-        return result;
-    }
-
-    private split(predicate: (t: Task) => boolean): [TaskList, TaskList] {
-        const matched: TaskList = [];
-        const other: TaskList = [];
-        this.getTasks().forEach(t => {
-            if (predicate(t)) {
-                matched.push(t);
-            } else {
-                other.push(t);
-            }
-        });
-        return [matched, other];
-    }
-
-    private storeTaskList(tasks: Array<Task>): void {
+    storeTaskList(tasks: Array<Task>): void {
         this.storage.set(TASK_LIST_KEY, tasks);
     }
 }
diff --git a/src/VillageController.ts b/src/VillageController.ts
index feab091..3b45118 100644
--- a/src/VillageController.ts
+++ b/src/VillageController.ts
@@ -1,93 +1,36 @@
-import { Task, TaskId, uniqTaskId, withResources, withTime } from './Queue/TaskProvider';
-import { VillageStorage } from './Storage/VillageStorage';
+import { VillageTaskCollection } from './VillageTaskCollection';
+import { Task, TaskId } from './Queue/TaskProvider';
 import { Args } from './Queue/Args';
-import { isProductionTask, ProductionQueue, ProductionQueueTypes } from './Core/ProductionQueue';
-import { Resources } from './Core/Resources';
-import { UpgradeBuildingTask } from './Task/UpgradeBuildingTask';
-import { ForgeImprovementTask } from './Task/ForgeImprovementTask';
-import { ContractType, ContractAttributes } from './Core/Contract';
-import { timestamp } from './utils';
-import { getProductionQueue } from './Task/TaskMap';
+import { VillageState } from './VillageState';
 
 export class VillageController {
-    private readonly _villageId: number;
-    private readonly _storage: VillageStorage;
+    private readonly villageId: number;
+    private taskCollection: VillageTaskCollection;
+    private readonly state: VillageState;
 
-    constructor(villageId: number, storage: VillageStorage) {
-        this._villageId = villageId;
-        this._storage = storage;
+    constructor(villageId: number, taskCollection: VillageTaskCollection, state: VillageState) {
+        this.villageId = villageId;
+        this.taskCollection = taskCollection;
+        this.state = state;
     }
 
-    get villageId() {
-        return this._villageId;
-    }
-
-    getStorage(): VillageStorage {
-        return this._storage;
-    }
-
-    addTask(name: string, args: Args) {
-        if (!isProductionTask(name)) {
-            throw new Error(`Task "${name}" is not production task`);
-        }
-        if (args.villageId !== this._villageId) {
-            throw new Error(`Task village id (${args.villageId}) not equal controller village id (${this._villageId}`);
-        }
-        const task = new Task(uniqTaskId(), 0, name, { villageId: this._villageId, ...args });
-        this._storage.addTask(task);
-    }
-
-    getTasks(): Array<Task> {
-        return this._storage.getTasks();
-    }
-
-    removeTask(taskId: TaskId) {
-        this._storage.removeTasks(t => t.id === taskId);
-    }
-
-    getTasksInProductionQueue(queue: ProductionQueue): Array<Task> {
-        return this._storage.getTasks().filter(task => getProductionQueue(task.name) === queue);
+    getVillageId() {
+        return this.villageId;
     }
 
     getReadyProductionTask(): Task | undefined {
-        let sortedTasks: Array<Task> = [];
-        for (let queue of ProductionQueueTypes) {
-            const tasks = this.getTasksInProductionQueue(queue);
-            sortedTasks = sortedTasks.concat(tasks);
-        }
-        return sortedTasks.shift();
+        return this.taskCollection.getReadyProductionTask();
+    }
+
+    addTask(name: string, args: Args) {
+        this.taskCollection.addTask(name, args);
+    }
+
+    removeTask(taskId: TaskId) {
+        this.taskCollection.removeTask(taskId);
     }
 
     postponeTask(taskId: TaskId, seconds: number) {
-        const modifyTime = withTime(timestamp() + seconds);
-        this._storage.modifyTasks(task => task.id === taskId, modifyTime);
-    }
-
-    updateResources(resources: Resources, attr: ContractAttributes): void {
-        if (attr.type === ContractType.UpgradeBuilding && attr.buildId) {
-            const predicate = (t: Task) => t.name === UpgradeBuildingTask.name && t.args.buildId === attr.buildId;
-            this._storage.modifyTasks(predicate, withResources(resources));
-        }
-        if (attr.type === ContractType.ImproveTrooper && attr.buildId && attr.unitId) {
-            const predicate = (t: Task) =>
-                t.name === ForgeImprovementTask.name &&
-                t.args.buildId === attr.buildId &&
-                t.args.unitId === attr.unitId;
-            this._storage.modifyTasks(predicate, withResources(resources));
-        }
-    }
-
-    getVillageRequiredResources(): Resources {
-        const tasks = this._storage.getTasks().filter(t => t.args.resources);
-        const first = tasks.shift();
-        if (first && first.args.resources) {
-            return Resources.fromObject(first.args.resources);
-        }
-        return Resources.zero();
-    }
-
-    getTotalVillageRequiredResources(): Resources {
-        const tasks = this._storage.getTasks().filter(t => t.args.resources);
-        return tasks.reduce((acc, t) => acc.add(t.args.resources!), Resources.zero());
+        this.taskCollection.postponeTask(taskId, seconds);
     }
 }
diff --git a/src/VillageControllerFactory.ts b/src/VillageControllerFactory.ts
deleted file mode 100644
index da46493..0000000
--- a/src/VillageControllerFactory.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import { VillageController } from './VillageController';
-import { VillageStorage } from './Storage/VillageStorage';
-import { VillageRepository } from './VillageRepository';
-
-export class VillageControllerFactory {
-    private villageRepository: VillageRepository;
-
-    constructor(villageRepository: VillageRepository) {
-        this.villageRepository = villageRepository;
-    }
-
-    create(villageId: number): VillageController {
-        const village = this.villageRepository.get(villageId);
-        return new VillageController(village.id, new VillageStorage(village.id));
-    }
-
-    getActive(): VillageController {
-        const village = this.villageRepository.getActive();
-        return this.create(village.id);
-    }
-}
diff --git a/src/VillageFactory.ts b/src/VillageFactory.ts
new file mode 100644
index 0000000..fce1435
--- /dev/null
+++ b/src/VillageFactory.ts
@@ -0,0 +1,57 @@
+import { VillageController } from './VillageController';
+import { VillageStorage } from './Storage/VillageStorage';
+import { VillageRepository } from './VillageRepository';
+import { VillageTaskCollection } from './VillageTaskCollection';
+import { VillageState, VillageStateFactory } from './VillageState';
+
+export class VillageFactory {
+    private readonly villageRepository: VillageRepository;
+
+    constructor(villageRepository: VillageRepository) {
+        this.villageRepository = villageRepository;
+    }
+
+    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();
+    }
+
+    createController(villageId: number): VillageController {
+        const village = this.villageRepository.get(villageId);
+        return new VillageController(village.id, this.createTaskCollection(village.id), this.createState(village.id));
+    }
+}
diff --git a/src/VillageState.ts b/src/VillageState.ts
index a67587d..c3c282e 100644
--- a/src/VillageState.ts
+++ b/src/VillageState.ts
@@ -7,8 +7,7 @@ import { VillageNotFound } from './Errors';
 import { ProductionQueue, ProductionQueueTypes } from './Core/ProductionQueue';
 import { Task } from './Queue/TaskProvider';
 import { timestamp } from './utils';
-import { VillageControllerFactory } from './VillageControllerFactory';
-import { VillageController } from './VillageController';
+import { VillageTaskCollection } from './VillageTaskCollection';
 
 interface VillageStorageState {
     resources: Resources;
@@ -134,12 +133,12 @@ function taskResourceReducer(resources: Resources, task: Task) {
 
 function createProductionQueueState(
     queue: ProductionQueue,
-    controller: VillageController
+    storage: VillageStorage,
+    taskCollection: VillageTaskCollection
 ): VillageProductionQueueState {
-    const storage = controller.getStorage();
     const resources = storage.getResources();
     const performance = storage.getResourcesPerformance();
-    const tasks = controller.getTasksInProductionQueue(queue);
+    const tasks = taskCollection.getTasksInProductionQueue(queue);
 
     const firstTaskResources = tasks.slice(0, 1).reduce(taskResourceReducer, Resources.zero());
     const allTaskResources = tasks.reduce(taskResourceReducer, Resources.zero());
@@ -156,33 +155,36 @@ function createProductionQueueState(
     };
 }
 
-function createAllProductionQueueStates(controller: VillageController) {
+function createAllProductionQueueStates(storage: VillageStorage, taskCollection: VillageTaskCollection) {
     let result: { [queue: string]: VillageProductionQueueState } = {};
     for (let queue of ProductionQueueTypes) {
-        result[queue] = createProductionQueueState(queue, controller);
+        result[queue] = createProductionQueueState(queue, storage, taskCollection);
     }
     return result;
 }
 
-function calcFrontierResources(controller: VillageController): Resources {
+function calcFrontierResources(taskCollection: VillageTaskCollection): Resources {
     let result = Resources.zero();
     for (let queue of ProductionQueueTypes) {
-        const tasks = controller.getTasksInProductionQueue(queue);
+        const tasks = taskCollection.getTasksInProductionQueue(queue);
         const firstTaskResources = tasks.slice(0, 1).reduce(taskResourceReducer, Resources.zero());
         result = result.add(firstTaskResources);
     }
     return result;
 }
 
-function createVillageOwnState(village: Village, controller: VillageController): VillageOwnState {
-    const storage = controller.getStorage();
+function createVillageOwnState(
+    village: Village,
+    storage: VillageStorage,
+    taskCollection: VillageTaskCollection
+): VillageOwnState {
     const resources = storage.getResources();
     const resourceStorage = storage.getResourceStorage();
     const performance = storage.getResourcesPerformance();
     const buildQueueInfo = storage.getBuildingQueueInfo();
-    const requiredResources = controller.getVillageRequiredResources();
-    const frontierResources = calcFrontierResources(controller);
-    const totalRequiredResources = controller.getTotalVillageRequiredResources();
+    const requiredResources = taskCollection.getVillageRequiredResources();
+    const frontierResources = calcFrontierResources(taskCollection);
+    const totalRequiredResources = taskCollection.getTotalVillageRequiredResources();
 
     return {
         id: village.id,
@@ -196,18 +198,22 @@ function createVillageOwnState(village: Village, controller: VillageController):
         buildRemainingSeconds: buildQueueInfo.seconds,
         incomingResources: calcIncomingResources(storage),
         settings: storage.getSettings(),
-        queues: createAllProductionQueueStates(controller),
+        queues: createAllProductionQueueStates(storage, taskCollection),
     };
 }
 
 function createVillageOwnStates(
     villages: Array<Village>,
-    villageControllerFactory: VillageControllerFactory
+    storageFactory: VillageStorageFactory,
+    taskCollectionFactory: VillageTaskCollectionFactory
 ): VillageOwnStateDictionary {
     const result: VillageOwnStateDictionary = {};
     for (let village of villages) {
-        const villageController = villageControllerFactory.create(village.id);
-        result[village.id] = createVillageOwnState(village, villageController);
+        result[village.id] = createVillageOwnState(
+            village,
+            storageFactory(village.id),
+            taskCollectionFactory(village.id)
+        );
     }
     return result;
 }
@@ -226,27 +232,42 @@ function createVillageState(state: VillageOwnState, ownStates: VillageOwnStateDi
 
 function getVillageStates(
     villages: Array<Village>,
-    villageControllerFactory: VillageControllerFactory
+    storageFactory: VillageStorageFactory,
+    taskCollectionFactory: VillageTaskCollectionFactory
 ): Array<VillageState> {
-    const ownStates = createVillageOwnStates(villages, villageControllerFactory);
+    const ownStates = createVillageOwnStates(villages, storageFactory, taskCollectionFactory);
     return villages.map(village => createVillageState(ownStates[village.id], ownStates));
 }
 
-export class VillageStateRepository {
-    private villageRepository: VillageRepositoryInterface;
-    private villageControllerFactory: VillageControllerFactory;
+interface VillageStorageFactory {
+    (villageId: number): VillageStorage;
+}
 
-    constructor(villageRepository: VillageRepositoryInterface, villageControllerFactory: VillageControllerFactory) {
+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.villageControllerFactory = villageControllerFactory;
+        this.storageFactory = storageFactory;
+        this.taskCollectionFactory = taskCollectionFactory;
     }
 
     getAllVillageStates(): Array<VillageState> {
-        return getVillageStates(this.villageRepository.all(), this.villageControllerFactory);
+        return getVillageStates(this.villageRepository.all(), this.storageFactory, this.taskCollectionFactory);
     }
 
     getVillageState(villageId: number): VillageState {
-        const states = getVillageStates(this.villageRepository.all(), this.villageControllerFactory);
+        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`);
diff --git a/src/VillageTaskCollection.ts b/src/VillageTaskCollection.ts
new file mode 100644
index 0000000..68c8c25
--- /dev/null
+++ b/src/VillageTaskCollection.ts
@@ -0,0 +1,116 @@
+import { VillageStorage } from './Storage/VillageStorage';
+import { Task, TaskId, TaskList, uniqTaskId, withResources, withTime } from './Queue/TaskProvider';
+import { Args } from './Queue/Args';
+import { isProductionTask, ProductionQueue, ProductionQueueTypes } from './Core/ProductionQueue';
+import { getProductionQueue } from './Task/TaskMap';
+import { timestamp } from './utils';
+import { Resources } from './Core/Resources';
+import { ContractAttributes, ContractType } from './Core/Contract';
+import { UpgradeBuildingTask } from './Task/UpgradeBuildingTask';
+import { ForgeImprovementTask } from './Task/ForgeImprovementTask';
+
+export class VillageTaskCollection {
+    private readonly storage: VillageStorage;
+    private readonly villageId: number;
+
+    constructor(villageId: number, storage: VillageStorage) {
+        this.villageId = villageId;
+        this.storage = storage;
+    }
+
+    getTasks(): Array<Task> {
+        return this.storage.getTasks();
+    }
+
+    private modifyTasks(predicate: (t: Task) => boolean, modifier: (t: Task) => Task): number {
+        const [matched, other] = this.split(predicate);
+        const modified = matched.map(modifier);
+        const modifiedCount = modified.length;
+        this.storage.storeTaskList(modified.concat(other));
+        return modifiedCount;
+    }
+
+    private removeTasks(predicate: (t: Task) => boolean): number {
+        const [_, other] = this.split(predicate);
+        const result = other.length;
+        this.storage.storeTaskList(other);
+        return result;
+    }
+
+    private split(predicate: (t: Task) => boolean): [TaskList, TaskList] {
+        const matched: TaskList = [];
+        const other: TaskList = [];
+        this.getTasks().forEach(t => {
+            if (predicate(t)) {
+                matched.push(t);
+            } else {
+                other.push(t);
+            }
+        });
+        return [matched, other];
+    }
+
+    addTask(name: string, args: Args) {
+        if (!isProductionTask(name)) {
+            throw new Error(`Task "${name}" is not production task`);
+        }
+        if (args.villageId !== this.villageId) {
+            throw new Error(`Task village id (${args.villageId}) not equal controller village id (${this.villageId}`);
+        }
+        const task = new Task(uniqTaskId(), 0, name, { villageId: this.villageId, ...args });
+
+        const tasks = this.getTasks();
+        tasks.push(task);
+        this.storage.storeTaskList(tasks);
+    }
+
+    removeTask(taskId: TaskId) {
+        this.removeTasks(t => t.id === taskId);
+    }
+
+    getTasksInProductionQueue(queue: ProductionQueue): Array<Task> {
+        return this.storage.getTasks().filter(task => getProductionQueue(task.name) === queue);
+    }
+
+    getReadyProductionTask(): Task | undefined {
+        let sortedTasks: Array<Task> = [];
+        for (let queue of ProductionQueueTypes) {
+            const tasks = this.getTasksInProductionQueue(queue);
+            sortedTasks = sortedTasks.concat(tasks);
+        }
+        return sortedTasks.shift();
+    }
+
+    postponeTask(taskId: TaskId, seconds: number) {
+        const modifyTime = withTime(timestamp() + seconds);
+        this.modifyTasks(task => task.id === taskId, modifyTime);
+    }
+
+    updateResources(resources: Resources, attr: ContractAttributes): void {
+        if (attr.type === ContractType.UpgradeBuilding && attr.buildId) {
+            const predicate = (t: Task) => t.name === UpgradeBuildingTask.name && t.args.buildId === attr.buildId;
+            this.modifyTasks(predicate, withResources(resources));
+        }
+        if (attr.type === ContractType.ImproveTrooper && attr.buildId && attr.unitId) {
+            const predicate = (t: Task) =>
+                t.name === ForgeImprovementTask.name &&
+                t.args.buildId === attr.buildId &&
+                t.args.unitId === attr.unitId;
+            this.modifyTasks(predicate, withResources(resources));
+        }
+    }
+
+    getVillageRequiredResources(): Resources {
+        const tasks = this.storage.getTasks().filter(t => t.args.resources);
+        const first = tasks.shift();
+        if (first && first.args.resources) {
+            return Resources.fromObject(first.args.resources);
+        }
+        return Resources.zero();
+    }
+
+    getTotalVillageRequiredResources(): Resources {
+        const tasks = this.storage.getTasks().filter(t => t.args.resources);
+        return tasks.reduce((acc, t) => acc.add(t.args.resources!), Resources.zero());
+    }
+}