Introduce production queues
And add queue state in village state list
This commit is contained in:
		
							
								
								
									
										29
									
								
								src/Core/ProductionQueue.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/Core/ProductionQueue.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | |||||||
|  | export enum ProductionQueue { | ||||||
|  |     Building = 'building', | ||||||
|  |     TrainUnit = 'train_unit', | ||||||
|  |     UpgradeUnit = 'upgrade_unit', | ||||||
|  |     Celebration = 'celebration', | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Placed in order of execution priority. Order is important! | ||||||
|  |  */ | ||||||
|  | export const ProductionQueueTypes: ReadonlyArray<ProductionQueue> = [ | ||||||
|  |     ProductionQueue.TrainUnit, | ||||||
|  |     ProductionQueue.Celebration, | ||||||
|  |     ProductionQueue.UpgradeUnit, | ||||||
|  |     ProductionQueue.Building, | ||||||
|  | ]; | ||||||
|  |  | ||||||
|  | export function translateProductionQueue(queue: ProductionQueue): string { | ||||||
|  |     switch (queue) { | ||||||
|  |         case ProductionQueue.Building: | ||||||
|  |             return 'Строительство'; | ||||||
|  |         case ProductionQueue.TrainUnit: | ||||||
|  |             return 'Обучение'; | ||||||
|  |         case ProductionQueue.UpgradeUnit: | ||||||
|  |             return 'Улучшение'; | ||||||
|  |         case ProductionQueue.Celebration: | ||||||
|  |             return 'Празднование'; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -48,6 +48,7 @@ | |||||||
|             </td> |             </td> | ||||||
|             <td class="right" v-text="storageTime(villageState)"></td> |             <td class="right" v-text="storageTime(villageState)"></td> | ||||||
|           </tr> |           </tr> | ||||||
|  |  | ||||||
|           <tr class="performance-line"> |           <tr class="performance-line"> | ||||||
|             <td class="right">Прирост:</td> |             <td class="right">Прирост:</td> | ||||||
|             <td class="right"> |             <td class="right"> | ||||||
| @@ -64,6 +65,7 @@ | |||||||
|             </td> |             </td> | ||||||
|             <td></td> |             <td></td> | ||||||
|           </tr> |           </tr> | ||||||
|  |  | ||||||
|           <tr class="required-line"> |           <tr class="required-line"> | ||||||
|             <td class="right">След. задача:</td> |             <td class="right">След. задача:</td> | ||||||
|             <td class="right"> |             <td class="right"> | ||||||
| @@ -100,6 +102,7 @@ | |||||||
|             </td> |             </td> | ||||||
|             <td class="right" v-text="renderTimeInSeconds(villageState.buildRemainingSeconds)"></td> |             <td class="right" v-text="renderTimeInSeconds(villageState.buildRemainingSeconds)"></td> | ||||||
|           </tr> |           </tr> | ||||||
|  |  | ||||||
|           <tr class="required-line"> |           <tr class="required-line"> | ||||||
|             <td class="right">Баланс задачи:</td> |             <td class="right">Баланс задачи:</td> | ||||||
|             <td class="right"> |             <td class="right"> | ||||||
| @@ -116,6 +119,7 @@ | |||||||
|             </td> |             </td> | ||||||
|             <td class="right" v-text="renderGatheringTime(villageState.required.time)"></td> |             <td class="right" v-text="renderGatheringTime(villageState.required.time)"></td> | ||||||
|           </tr> |           </tr> | ||||||
|  |  | ||||||
|           <tr class="required-line"> |           <tr class="required-line"> | ||||||
|             <td class="right">Баланс очереди:</td> |             <td class="right">Баланс очереди:</td> | ||||||
|             <td class="right"> |             <td class="right"> | ||||||
| @@ -132,6 +136,24 @@ | |||||||
|             </td> |             </td> | ||||||
|             <td class="right" v-text="renderGatheringTime(villageState.totalRequired.time)"></td> |             <td class="right" v-text="renderGatheringTime(villageState.totalRequired.time)"></td> | ||||||
|           </tr> |           </tr> | ||||||
|  |  | ||||||
|  |           <tr v-for="queueState of villageState.queues" v-if="queueState.active" class="required-line"> | ||||||
|  |             <td class="right">{{ queueTitle(queueState.queue) }}:</td> | ||||||
|  |             <td class="right"> | ||||||
|  |               <resource :value="queueState.firstTask.balance.lumber"></resource> | ||||||
|  |             </td> | ||||||
|  |             <td class="right"> | ||||||
|  |               <resource :value="queueState.firstTask.balance.clay"></resource> | ||||||
|  |             </td> | ||||||
|  |             <td class="right"> | ||||||
|  |               <resource :value="queueState.firstTask.balance.iron"></resource> | ||||||
|  |             </td> | ||||||
|  |             <td class="right"> | ||||||
|  |               <resource :value="queueState.firstTask.balance.crop"></resource> | ||||||
|  |             </td> | ||||||
|  |             <td class="right" v-text="renderGatheringTime(queueState.firstTask.time)"></td> | ||||||
|  |           </tr> | ||||||
|  |  | ||||||
|           <tr class="commitments-line" v-if="!villageState.commitments.empty()"> |           <tr class="commitments-line" v-if="!villageState.commitments.empty()"> | ||||||
|             <td class="right">Обязательства:</td> |             <td class="right">Обязательства:</td> | ||||||
|             <td class="right"> |             <td class="right"> | ||||||
| @@ -206,6 +228,7 @@ import VillageResource from './VillageResource'; | |||||||
| import { COLLECTION_POINT_ID, HORSE_STABLE_ID, MARKET_ID, QUARTERS_ID } from '../Core/Buildings'; | import { COLLECTION_POINT_ID, HORSE_STABLE_ID, MARKET_ID, QUARTERS_ID } from '../Core/Buildings'; | ||||||
| import { path } from '../Helpers/Path'; | import { path } from '../Helpers/Path'; | ||||||
| import { Actions } from './Store'; | import { Actions } from './Store'; | ||||||
|  | import { translateProductionQueue } from '../Core/ProductionQueue'; | ||||||
|  |  | ||||||
| function secondsToTime(value) { | function secondsToTime(value) { | ||||||
|   if (value === 0) { |   if (value === 0) { | ||||||
| @@ -295,6 +318,9 @@ export default { | |||||||
|     openEditor(villageId) { |     openEditor(villageId) { | ||||||
|       this.$store.dispatch(Actions.OpenVillageEditor, { villageId }); |       this.$store.dispatch(Actions.OpenVillageEditor, { villageId }); | ||||||
|     }, |     }, | ||||||
|  |     queueTitle(queue) { | ||||||
|  |       return translateProductionQueue(queue); | ||||||
|  |     }, | ||||||
|   }, |   }, | ||||||
| }; | }; | ||||||
| </script> | </script> | ||||||
|   | |||||||
| @@ -1,9 +1,10 @@ | |||||||
| import { Grabber } from './Grabber'; | import { Grabber } from './Grabber'; | ||||||
| import { grabActiveVillageId, grabBuildingQueueInfo, grabResourcesPerformance } from '../Page/VillageBlock'; | import { grabActiveVillageId, grabBuildingQueueInfo, grabResourcesPerformance } from '../Page/VillageBlock'; | ||||||
| import { VillageStorage } from '../Storage/VillageStorage'; | import { VillageStorage } from '../Storage/VillageStorage'; | ||||||
| import { parseLocation } from '../utils'; | import { parseLocation, timestamp } from '../utils'; | ||||||
| import { GrabError } from '../Errors'; | import { GrabError } from '../Errors'; | ||||||
| import { BuildingQueueInfo } from '../Game'; | import { BuildingQueueInfo } from '../Game'; | ||||||
|  | import { ProductionQueue } from '../Core/ProductionQueue'; | ||||||
|  |  | ||||||
| export class VillageOverviewPageGrabber extends Grabber { | export class VillageOverviewPageGrabber extends Grabber { | ||||||
|     grab(): void { |     grab(): void { | ||||||
| @@ -13,9 +14,13 @@ export class VillageOverviewPageGrabber extends Grabber { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         const villageId = grabActiveVillageId(); |         const villageId = grabActiveVillageId(); | ||||||
|         const state = new VillageStorage(villageId); |         const storage = new VillageStorage(villageId); | ||||||
|         state.storeResourcesPerformance(grabResourcesPerformance()); |         storage.storeResourcesPerformance(grabResourcesPerformance()); | ||||||
|         state.storeBuildingQueueInfo(this.grabBuildingQueueInfoOrDefault()); |         storage.storeBuildingQueueInfo(this.grabBuildingQueueInfoOrDefault()); | ||||||
|  |  | ||||||
|  |         const buildingQueueInfo = this.grabBuildingQueueInfoOrDefault(); | ||||||
|  |         const buildingEndTime = buildingQueueInfo.seconds ? buildingQueueInfo.seconds + timestamp() : 0; | ||||||
|  |         storage.storeQueueTaskEnding(ProductionQueue.Building, buildingEndTime); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private grabBuildingQueueInfoOrDefault() { |     private grabBuildingQueueInfoOrDefault() { | ||||||
|   | |||||||
| @@ -12,9 +12,10 @@ import { SendResourcesTask } from './Task/SendResourcesTask'; | |||||||
| import { Args } from './Queue/Args'; | import { Args } from './Queue/Args'; | ||||||
| import { ImmutableTaskList, Task, TaskId } from './Queue/TaskProvider'; | import { ImmutableTaskList, Task, TaskId } from './Queue/TaskProvider'; | ||||||
| import { ForgeImprovementTask } from './Task/ForgeImprovementTask'; | import { ForgeImprovementTask } from './Task/ForgeImprovementTask'; | ||||||
| import { getTaskType, TaskType } from './Task/TaskMap'; | import { getProductionQueue } from './Task/TaskMap'; | ||||||
| import { MARKET_ID } from './Core/Buildings'; | import { MARKET_ID } from './Core/Buildings'; | ||||||
| import { VillageRepositoryInterface } from './VillageRepository'; | import { VillageRepositoryInterface } from './VillageRepository'; | ||||||
|  | import { ProductionQueue, ProductionQueueTypes } from './Core/ProductionQueue'; | ||||||
|  |  | ||||||
| export enum ContractType { | export enum ContractType { | ||||||
|     UpgradeBuilding, |     UpgradeBuilding, | ||||||
| @@ -205,6 +206,12 @@ export class Scheduler { | |||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     getProductionQueueTasks(villageId: number, queue: ProductionQueue): ReadonlyArray<Task> { | ||||||
|  |         return this.taskQueue | ||||||
|  |             .seeItems() | ||||||
|  |             .filter(t => t.args.villageId === villageId && getProductionQueue(t.name) === queue); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     private reorderVillageTasks(villageId: number) { |     private reorderVillageTasks(villageId: number) { | ||||||
|         const tasks = this.taskQueue.seeItems(); |         const tasks = this.taskQueue.seeItems(); | ||||||
|  |  | ||||||
| @@ -229,16 +236,11 @@ interface TaskNamePredicate { | |||||||
| } | } | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * List on non intersected task type predicates. |  * List on non intersected task queue predicates. | ||||||
|  * |  | ||||||
|  * Placed in order of execution priority. Order is important! |  | ||||||
|  */ |  */ | ||||||
| const TASK_TYPE_PREDICATES: Array<TaskNamePredicate> = [ | const TASK_TYPE_PREDICATES: Array<TaskNamePredicate> = ProductionQueueTypes.map(queue => { | ||||||
|     (taskName: string) => getTaskType(taskName) === TaskType.TrainUnit, |     return (taskName: string) => getProductionQueue(taskName) === queue; | ||||||
|     (taskName: string) => getTaskType(taskName) === TaskType.UpgradeUnit, | }); | ||||||
|     (taskName: string) => getTaskType(taskName) === TaskType.Building, |  | ||||||
|     (taskName: string) => getTaskType(taskName) === TaskType.Celebration, |  | ||||||
| ]; |  | ||||||
|  |  | ||||||
| function sameVillage(villageId: number | undefined, args: Args) { | function sameVillage(villageId: number | undefined, args: Args) { | ||||||
|     return villageId !== undefined && args.villageId === villageId; |     return villageId !== undefined && args.villageId === villageId; | ||||||
| @@ -273,7 +275,7 @@ function findLastIndex(tasks: ImmutableTaskList, predicate: (t: Task) => boolean | |||||||
| } | } | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Calculates insert time for new task based on task type. |  * Calculates insert time for new task based on task queue. | ||||||
|  */ |  */ | ||||||
| function calculateInsertTime(tasks: ImmutableTaskList, name: string, args: Args, ts: number | undefined): number { | function calculateInsertTime(tasks: ImmutableTaskList, name: string, args: Args, ts: number | undefined): number { | ||||||
|     const villageId = args.villageId; |     const villageId = args.villageId; | ||||||
|   | |||||||
| @@ -4,6 +4,8 @@ import { Resources, ResourcesInterface } from '../Core/Resources'; | |||||||
| import { ResourceStorage } from '../Core/ResourceStorage'; | import { ResourceStorage } from '../Core/ResourceStorage'; | ||||||
| import { IncomingMerchant } from '../Core/Market'; | import { IncomingMerchant } from '../Core/Market'; | ||||||
| import { VillageSettings, VillageSettingsDefaults } from '../Core/Village'; | import { VillageSettings, VillageSettingsDefaults } from '../Core/Village'; | ||||||
|  | import { ProductionQueue } from '../Core/ProductionQueue'; | ||||||
|  | import { getNumber } from '../utils'; | ||||||
|  |  | ||||||
| const RESOURCES_KEY = 'res'; | const RESOURCES_KEY = 'res'; | ||||||
| const CAPACITY_KEY = 'cap'; | const CAPACITY_KEY = 'cap'; | ||||||
| @@ -11,6 +13,7 @@ const PERFORMANCE_KEY = 'perf'; | |||||||
| const BUILDING_QUEUE_KEY = 'bq'; | const BUILDING_QUEUE_KEY = 'bq'; | ||||||
| const INCOMING_MERCHANTS_KEY = 'im'; | const INCOMING_MERCHANTS_KEY = 'im'; | ||||||
| const SETTINGS_KEY = 'settings'; | const SETTINGS_KEY = 'settings'; | ||||||
|  | const QUEUE_ENDING_TIME_KEY = 'qet'; | ||||||
|  |  | ||||||
| const ResourceOptions = { | const ResourceOptions = { | ||||||
|     factory: () => new Resources(0, 0, 0, 0), |     factory: () => new Resources(0, 0, 0, 0), | ||||||
| @@ -86,4 +89,18 @@ export class VillageStorage { | |||||||
|     storeSettings(settings: VillageSettings) { |     storeSettings(settings: VillageSettings) { | ||||||
|         this.storage.set(SETTINGS_KEY, settings); |         this.storage.set(SETTINGS_KEY, settings); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     private queueKey(queue: ProductionQueue): string { | ||||||
|  |         return QUEUE_ENDING_TIME_KEY + '.' + queue; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     getQueueTaskEnding(queue: ProductionQueue): number { | ||||||
|  |         const key = this.queueKey(queue); | ||||||
|  |         return getNumber(this.storage.get(key)) || 0; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     storeQueueTaskEnding(queue: ProductionQueue, ts: number): void { | ||||||
|  |         const key = this.queueKey(queue); | ||||||
|  |         this.storage.set(key, ts); | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -3,11 +3,12 @@ import { GoToPageAction } from '../Action/GoToPageAction'; | |||||||
| import { ActionDefinition, TaskController } from './TaskController'; | import { ActionDefinition, TaskController } from './TaskController'; | ||||||
| import { Task } from '../Queue/TaskProvider'; | import { Task } from '../Queue/TaskProvider'; | ||||||
| import { path } from '../Helpers/Path'; | import { path } from '../Helpers/Path'; | ||||||
| import { registerTask, TaskType } from './TaskMap'; | import { registerTask } from './TaskMap'; | ||||||
| import { taskError } from '../Errors'; | import { taskError } from '../Errors'; | ||||||
| import { goToResourceViewPage } from './ActionBundles'; | import { goToResourceViewPage } from './ActionBundles'; | ||||||
|  | import { ProductionQueue } from '../Core/ProductionQueue'; | ||||||
|  |  | ||||||
| @registerTask({ type: TaskType.Building }) | @registerTask({ queue: ProductionQueue.Building }) | ||||||
| export class BuildBuildingTask extends TaskController { | export class BuildBuildingTask extends TaskController { | ||||||
|     defineActions(task: Task): Array<ActionDefinition> { |     defineActions(task: Task): Array<ActionDefinition> { | ||||||
|         const args = task.args; |         const args = task.args; | ||||||
|   | |||||||
| @@ -3,9 +3,10 @@ import { GoToPageAction } from '../Action/GoToPageAction'; | |||||||
| import { Task } from '../Queue/TaskProvider'; | import { Task } from '../Queue/TaskProvider'; | ||||||
| import { path } from '../Helpers/Path'; | import { path } from '../Helpers/Path'; | ||||||
| import { CelebrationAction } from '../Action/CelebrationAction'; | import { CelebrationAction } from '../Action/CelebrationAction'; | ||||||
| import { registerTask, TaskType } from './TaskMap'; | import { registerTask } from './TaskMap'; | ||||||
|  | import { ProductionQueue } from '../Core/ProductionQueue'; | ||||||
|  |  | ||||||
| @registerTask({ type: TaskType.Celebration }) | @registerTask({ queue: ProductionQueue.Celebration }) | ||||||
| export class CelebrationTask extends TaskController { | export class CelebrationTask extends TaskController { | ||||||
|     defineActions(task: Task): Array<ActionDefinition> { |     defineActions(task: Task): Array<ActionDefinition> { | ||||||
|         const args = task.args; |         const args = task.args; | ||||||
|   | |||||||
| @@ -3,9 +3,10 @@ import { GoToPageAction } from '../Action/GoToPageAction'; | |||||||
| import { Task } from '../Queue/TaskProvider'; | import { Task } from '../Queue/TaskProvider'; | ||||||
| import { ForgeImprovementAction } from '../Action/ForgeImprovementAction'; | import { ForgeImprovementAction } from '../Action/ForgeImprovementAction'; | ||||||
| import { path } from '../Helpers/Path'; | import { path } from '../Helpers/Path'; | ||||||
| import { registerTask, TaskType } from './TaskMap'; | import { registerTask } from './TaskMap'; | ||||||
|  | import { ProductionQueue } from '../Core/ProductionQueue'; | ||||||
|  |  | ||||||
| @registerTask({ type: TaskType.UpgradeUnit }) | @registerTask({ queue: ProductionQueue.UpgradeUnit }) | ||||||
| export class ForgeImprovementTask extends TaskController { | export class ForgeImprovementTask extends TaskController { | ||||||
|     defineActions(task: Task): Array<ActionDefinition> { |     defineActions(task: Task): Array<ActionDefinition> { | ||||||
|         const args = task.args; |         const args = task.args; | ||||||
|   | |||||||
| @@ -1,21 +1,14 @@ | |||||||
| import { Scheduler } from '../Scheduler'; | import { Scheduler } from '../Scheduler'; | ||||||
| import { TaskController } from './TaskController'; | import { TaskController } from './TaskController'; | ||||||
|  | import { ProductionQueue } from '../Core/ProductionQueue'; | ||||||
| export enum TaskType { |  | ||||||
|     Other = 1, |  | ||||||
|     Building, |  | ||||||
|     TrainUnit, |  | ||||||
|     UpgradeUnit, |  | ||||||
|     Celebration, |  | ||||||
| } |  | ||||||
|  |  | ||||||
| interface TaskOptions { | interface TaskOptions { | ||||||
|     type?: TaskType; |     queue?: ProductionQueue; | ||||||
| } | } | ||||||
|  |  | ||||||
| interface TaskDescription { | interface TaskDescription { | ||||||
|     ctor: Function; |     ctor: Function; | ||||||
|     type: TaskType; |     queue?: ProductionQueue; | ||||||
| } | } | ||||||
|  |  | ||||||
| interface TaskMap { | interface TaskMap { | ||||||
| @@ -28,17 +21,17 @@ export function registerTask(options: TaskOptions = {}) { | |||||||
|     return function(ctor: Function) { |     return function(ctor: Function) { | ||||||
|         taskMap[ctor.name] = { |         taskMap[ctor.name] = { | ||||||
|             ctor, |             ctor, | ||||||
|             type: options.type || TaskType.Other, |             queue: options.queue, | ||||||
|         }; |         }; | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
|  |  | ||||||
| export function getTaskType(name: string): TaskType | undefined { | export function getProductionQueue(name: string): ProductionQueue | undefined { | ||||||
|     const taskDescription = taskMap[name]; |     const taskDescription = taskMap[name]; | ||||||
|     if (taskDescription === undefined) { |     if (taskDescription === undefined) { | ||||||
|         return undefined; |         return undefined; | ||||||
|     } |     } | ||||||
|     return taskDescription.type; |     return taskDescription.queue; | ||||||
| } | } | ||||||
|  |  | ||||||
| export function createTaskHandler(name: string, scheduler: Scheduler): TaskController | undefined { | export function createTaskHandler(name: string, scheduler: Scheduler): TaskController | undefined { | ||||||
|   | |||||||
| @@ -4,9 +4,10 @@ import { CompleteTaskAction } from '../Action/CompleteTaskAction'; | |||||||
| import { TrainTrooperAction } from '../Action/TrainTrooperAction'; | import { TrainTrooperAction } from '../Action/TrainTrooperAction'; | ||||||
| import { Task } from '../Queue/TaskProvider'; | import { Task } from '../Queue/TaskProvider'; | ||||||
| import { path } from '../Helpers/Path'; | import { path } from '../Helpers/Path'; | ||||||
| import { registerTask, TaskType } from './TaskMap'; | import { registerTask } from './TaskMap'; | ||||||
|  | import { ProductionQueue } from '../Core/ProductionQueue'; | ||||||
|  |  | ||||||
| @registerTask({ type: TaskType.TrainUnit }) | @registerTask({ queue: ProductionQueue.TrainUnit }) | ||||||
| export class TrainTroopTask extends TaskController { | export class TrainTroopTask extends TaskController { | ||||||
|     defineActions(task: Task): Array<ActionDefinition> { |     defineActions(task: Task): Array<ActionDefinition> { | ||||||
|         const args = task.args; |         const args = task.args; | ||||||
|   | |||||||
| @@ -3,11 +3,12 @@ import { TaskController, ActionDefinition } from './TaskController'; | |||||||
| import { GoToPageAction } from '../Action/GoToPageAction'; | import { GoToPageAction } from '../Action/GoToPageAction'; | ||||||
| import { Task } from '../Queue/TaskProvider'; | import { Task } from '../Queue/TaskProvider'; | ||||||
| import { path } from '../Helpers/Path'; | import { path } from '../Helpers/Path'; | ||||||
| import { registerTask, TaskType } from './TaskMap'; | import { registerTask } from './TaskMap'; | ||||||
| import { goToResourceViewPage } from './ActionBundles'; | import { goToResourceViewPage } from './ActionBundles'; | ||||||
| import { taskError } from '../Errors'; | import { taskError } from '../Errors'; | ||||||
|  | import { ProductionQueue } from '../Core/ProductionQueue'; | ||||||
|  |  | ||||||
| @registerTask({ type: TaskType.Building }) | @registerTask({ queue: ProductionQueue.Building }) | ||||||
| export class UpgradeBuildingTask extends TaskController { | export class UpgradeBuildingTask extends TaskController { | ||||||
|     defineActions(task: Task): Array<ActionDefinition> { |     defineActions(task: Task): Array<ActionDefinition> { | ||||||
|         const args = task.args; |         const args = task.args; | ||||||
|   | |||||||
| @@ -5,6 +5,8 @@ import { VillageStorage } from './Storage/VillageStorage'; | |||||||
| import { calcGatheringTimings, GatheringTime } from './Core/GatheringTimings'; | import { calcGatheringTimings, GatheringTime } from './Core/GatheringTimings'; | ||||||
| import { VillageRepositoryInterface } from './VillageRepository'; | import { VillageRepositoryInterface } from './VillageRepository'; | ||||||
| import { VillageNotFound } from './Errors'; | import { VillageNotFound } from './Errors'; | ||||||
|  | import { ProductionQueue, ProductionQueueTypes } from './Core/ProductionQueue'; | ||||||
|  | import { Task } from './Queue/TaskProvider'; | ||||||
|  |  | ||||||
| interface VillageStorageState { | interface VillageStorageState { | ||||||
|     resources: Resources; |     resources: Resources; | ||||||
| @@ -15,7 +17,10 @@ interface VillageStorageState { | |||||||
|     timeToFull: GatheringTime; |     timeToFull: GatheringTime; | ||||||
| } | } | ||||||
|  |  | ||||||
| interface RequiredResources { | /** | ||||||
|  |  * State of one or more tasks, which required some resources. | ||||||
|  |  */ | ||||||
|  | interface ResourceLineState { | ||||||
|     /** |     /** | ||||||
|      * Required resources (always positive) |      * Required resources (always positive) | ||||||
|      */ |      */ | ||||||
| @@ -30,6 +35,14 @@ interface RequiredResources { | |||||||
|     time: GatheringTime; |     time: GatheringTime; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | interface VillageProductionQueueState { | ||||||
|  |     queue: ProductionQueue; | ||||||
|  |     active: boolean; | ||||||
|  |     ts: number; | ||||||
|  |     firstTask: ResourceLineState; | ||||||
|  |     allTasks: ResourceLineState; | ||||||
|  | } | ||||||
|  |  | ||||||
| interface VillageOwnState { | interface VillageOwnState { | ||||||
|     /** |     /** | ||||||
|      * Village id |      * Village id | ||||||
| @@ -48,14 +61,15 @@ interface VillageOwnState { | |||||||
|     /** |     /** | ||||||
|      * Required resources for nearest task |      * Required resources for nearest task | ||||||
|      */ |      */ | ||||||
|     required: RequiredResources; |     required: ResourceLineState; | ||||||
|     /** |     /** | ||||||
|      * Required resources for all tasks |      * Required resources for all tasks | ||||||
|      */ |      */ | ||||||
|     totalRequired: RequiredResources; |     totalRequired: ResourceLineState; | ||||||
|     incomingResources: Resources; |     incomingResources: Resources; | ||||||
|     buildRemainingSeconds: number; |     buildRemainingSeconds: number; | ||||||
|     settings: VillageSettings; |     settings: VillageSettings; | ||||||
|  |     queues: { [queue: string]: VillageProductionQueueState | undefined }; | ||||||
| } | } | ||||||
|  |  | ||||||
| interface VillageOwnStateDictionary { | interface VillageOwnStateDictionary { | ||||||
| @@ -73,7 +87,7 @@ export interface VillageState extends VillageOwnState { | |||||||
|     shipment: Array<number>; |     shipment: Array<number>; | ||||||
| } | } | ||||||
|  |  | ||||||
| function calcResourceBalance(resources: Resources, current: Resources, performance: Resources): RequiredResources { | function calcResourceBalance(resources: Resources, current: Resources, performance: Resources): ResourceLineState { | ||||||
|     return { |     return { | ||||||
|         resources, |         resources, | ||||||
|         balance: current.sub(resources), |         balance: current.sub(resources), | ||||||
| @@ -106,6 +120,50 @@ function calcIncomingResources(storage: VillageStorage): Resources { | |||||||
|     return storage.getIncomingMerchants().reduce((m, i) => m.add(i.resources), Resources.zero()); |     return storage.getIncomingMerchants().reduce((m, i) => m.add(i.resources), Resources.zero()); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | function taskResourceReducer(resources: Resources, task: Task) { | ||||||
|  |     return task.args.resources ? resources.add(Resources.fromObject(task.args.resources)) : resources; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function createProductionQueueState( | ||||||
|  |     villageId: number, | ||||||
|  |     queue: ProductionQueue, | ||||||
|  |     storage: VillageStorage, | ||||||
|  |     scheduler: Scheduler | ||||||
|  | ): VillageProductionQueueState { | ||||||
|  |     const resources = storage.getResources(); | ||||||
|  |     const performance = storage.getResourcesPerformance(); | ||||||
|  |     const tasks = scheduler.getProductionQueueTasks(villageId, queue); | ||||||
|  |  | ||||||
|  |     const firstTaskResources = tasks.slice(0, 1).reduce(taskResourceReducer, Resources.zero()); | ||||||
|  |     const allTaskResources = tasks.reduce(taskResourceReducer, Resources.zero()); | ||||||
|  |  | ||||||
|  |     return { | ||||||
|  |         queue, | ||||||
|  |         active: tasks.length !== 0, | ||||||
|  |         ts: storage.getQueueTaskEnding(queue), | ||||||
|  |         firstTask: calcResourceBalance(firstTaskResources, resources, performance), | ||||||
|  |         allTasks: calcResourceBalance(allTaskResources, resources, performance), | ||||||
|  |     }; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function createAllProductionQueueStates(villageId: number, storage: VillageStorage, scheduler: Scheduler) { | ||||||
|  |     let result: { [queue: string]: VillageProductionQueueState } = {}; | ||||||
|  |     for (let queue of ProductionQueueTypes) { | ||||||
|  |         result[queue] = createProductionQueueState(villageId, queue, storage, scheduler); | ||||||
|  |     } | ||||||
|  |     return result; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // function firstTaskRequirements(villageId: number, scheduler: Scheduler): Resources { | ||||||
|  | //     let result = Resources.zero(); | ||||||
|  | //     for (let queue of Object.keys(ProductionQueue)) { | ||||||
|  | //         const tasks = scheduler.getProductionQueueTasks(villageId, queue as ProductionQueue); | ||||||
|  | //         const firstTaskResources = tasks.filter(() => true).reduce(taskResourceReducer, Resources.zero()); | ||||||
|  | //         result = result.add(firstTaskResources); | ||||||
|  | //     } | ||||||
|  | //     return result; | ||||||
|  | // } | ||||||
|  |  | ||||||
| function createVillageOwnState(village: Village, scheduler: Scheduler): VillageOwnState { | function createVillageOwnState(village: Village, scheduler: Scheduler): VillageOwnState { | ||||||
|     const storage = new VillageStorage(village.id); |     const storage = new VillageStorage(village.id); | ||||||
|     const resources = storage.getResources(); |     const resources = storage.getResources(); | ||||||
| @@ -126,6 +184,7 @@ function createVillageOwnState(village: Village, scheduler: Scheduler): VillageO | |||||||
|         buildRemainingSeconds: buildQueueInfo.seconds, |         buildRemainingSeconds: buildQueueInfo.seconds, | ||||||
|         incomingResources: calcIncomingResources(storage), |         incomingResources: calcIncomingResources(storage), | ||||||
|         settings: storage.getSettings(), |         settings: storage.getSettings(), | ||||||
|  |         queues: createAllProductionQueueStates(village.id, storage, scheduler), | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user