From 277a3381647da88f0471b46ffdfeed195fa483ee Mon Sep 17 00:00:00 2001 From: Anton Vakhrushev Date: Sat, 6 Jun 2020 21:39:35 +0300 Subject: [PATCH] Move first task calculation to state --- src/DashboardView/VillageStateList.vue | 3 + src/VillageController.ts | 2 +- src/VillageState.ts | 86 +++++++++++++++++++------- src/VillageTaskCollection.ts | 35 +---------- 4 files changed, 68 insertions(+), 58 deletions(-) diff --git a/src/DashboardView/VillageStateList.vue b/src/DashboardView/VillageStateList.vue index 40a48cd..a8cecff 100644 --- a/src/DashboardView/VillageStateList.vue +++ b/src/DashboardView/VillageStateList.vue @@ -68,6 +68,9 @@ diff --git a/src/VillageController.ts b/src/VillageController.ts index 82cdef6..4375a43 100644 --- a/src/VillageController.ts +++ b/src/VillageController.ts @@ -35,7 +35,7 @@ export class VillageController { } getReadyProductionTask(): Task | undefined { - return this.taskCollection.getReadyForProductionTask(); + return this.state.firstReadyTask; } addTask(name: string, args: Args) { diff --git a/src/VillageState.ts b/src/VillageState.ts index e30e7b4..1b97f6a 100644 --- a/src/VillageState.ts +++ b/src/VillageState.ts @@ -4,10 +4,11 @@ import { VillageStorage } from './Storage/VillageStorage'; import { calcGatheringTimings, GatheringTime } from './Core/GatheringTimings'; import { VillageRepositoryInterface } from './VillageRepository'; import { VillageNotFound } from './Errors'; -import { ProductionQueue, OrderedProductionQueues } from './Core/ProductionQueue'; +import { ProductionQueue } from './Core/ProductionQueue'; import { Task } from './Queue/TaskProvider'; import { timestamp } from './utils'; -import { VillageTaskCollection } from './VillageTaskCollection'; +import { QueueTasks, VillageTaskCollection } from './VillageTaskCollection'; +import { TrainTroopTask } from './Task/TrainTroopTask'; interface VillageStorageState { resources: Resources; @@ -42,6 +43,7 @@ interface ResourceLineState { interface VillageProductionQueueState { queue: ProductionQueue; + tasks: Array; isActive: boolean; currentTaskFinishTimestamp: number; currentTaskFinishSeconds: number; @@ -50,6 +52,10 @@ interface VillageProductionQueueState { taskCount: number; } +interface VillageProductionQueueStateDict { + [queue: string]: VillageProductionQueueState; +} + interface VillageOwnState { /** * Village id @@ -68,6 +74,8 @@ interface VillageOwnState { upperCriticalLevel: Resources; storageOptimumFullness: Resources; isOverflowing: boolean; + queues: VillageProductionQueueStateDict; + firstReadyTask: Task | undefined; /** * Required resources for nearest task */ @@ -82,7 +90,6 @@ interface VillageOwnState { totalRequired: ResourceLineState; incomingResources: Resources; settings: VillageSettings; - queues: { [queue: string]: VillageProductionQueueState | undefined }; } interface VillageOwnStateDictionary { @@ -96,7 +103,7 @@ export interface VillageState extends VillageOwnState { commitments: Resources; } -function calcResourceBalance( +function makeResourceBalance( resources: Resources, current: Resources, performance: Resources @@ -109,7 +116,7 @@ function calcResourceBalance( }; } -function calcStorageBalance( +function makeStorageBalance( resources: Resources, storage: Resources, performance: Resources @@ -153,28 +160,29 @@ function taskResourceReducer(resources: Resources, task: Task) { } function createProductionQueueState( - queue: ProductionQueue, - storage: VillageStorage, - taskCollection: VillageTaskCollection + taskQueueInfo: QueueTasks, + storage: VillageStorage ): VillageProductionQueueState { + const queue = taskQueueInfo.queue; + const tasks = taskQueueInfo.tasks; const resources = storage.getResources(); const performance = storage.getResourcesPerformance(); - const tasks = taskCollection.getTasksInProductionQueue(queue); const firstTaskResources = tasks.slice(0, 1).reduce(taskResourceReducer, Resources.zero()); const allTaskResources = tasks.reduce(taskResourceReducer, Resources.zero()); - const taskEndingTimestamp = storage.getQueueTaskEnding(queue); + const taskEndingTimestamp = taskQueueInfo.finishTs; return { queue, + tasks, isActive: tasks.length !== 0 || taskEndingTimestamp > timestamp(), currentTaskFinishTimestamp: taskEndingTimestamp, currentTaskFinishSeconds: Math.max( taskEndingTimestamp ? taskEndingTimestamp - timestamp() : 0, 0 ), - firstTask: calcResourceBalance(firstTaskResources, resources, performance), - allTasks: calcResourceBalance(allTaskResources, resources, performance), + firstTask: makeResourceBalance(firstTaskResources, resources, performance), + allTasks: makeResourceBalance(allTaskResources, resources, performance), taskCount: tasks.length, }; } @@ -183,25 +191,54 @@ function createAllProductionQueueStates( storage: VillageStorage, taskCollection: VillageTaskCollection ) { - let result: { [queue: string]: VillageProductionQueueState } = {}; - for (let queue of OrderedProductionQueues) { - result[queue] = createProductionQueueState(queue, storage, taskCollection); + let result: VillageProductionQueueStateDict = {}; + for (let taskQueueInfo of taskCollection.getQueueGroupedTasks()) { + result[taskQueueInfo.queue] = createProductionQueueState(taskQueueInfo, storage); } return result; } +function getReadyForProductionTask( + queues: VillageProductionQueueStateDict, + maxResourcesForTask: Resources +): Task | undefined { + const nowTs = timestamp(); + const firstReadyGroup = Object.values(queues).find( + group => group.currentTaskFinishTimestamp <= nowTs && group.tasks.length !== 0 + ); + if (!firstReadyGroup) { + return undefined; + } + + return firstReadyGroup.tasks.find( + t => + t.name === TrainTroopTask.name || + !t.args.resources || + maxResourcesForTask.allGreaterOrEqual(Resources.fromObject(t.args.resources)) + ); +} + +function getReadyTaskRequiredResources(task: Task | undefined): Resources { + if (task && task.args.resources) { + return Resources.fromObject(task.args.resources); + } + return Resources.zero(); +} + function createVillageOwnState( village: Village, storage: VillageStorage, taskCollection: VillageTaskCollection ): VillageOwnState { const resources = storage.getResources(); - const resourceStorage = storage.getResourceStorage(); + const storageResources = Resources.fromStorage(storage.getResourceStorage()); const performance = storage.getResourcesPerformance(); - const upperCriticalLevel = Resources.fromStorage(resourceStorage).sub(performance.scale(1)); - const storageOptimumFullness = Resources.fromStorage(resourceStorage).sub(performance.scale(3)); + const upperCriticalLevel = storageResources.sub(performance.scale(1)); + const storageOptimumFullness = storageResources.sub(performance.scale(3)); const isOverflowing = upperCriticalLevel.anyLower(resources); - const requiredResources = taskCollection.getReadyTaskRequiredResources(); + const queues = createAllProductionQueueStates(storage, taskCollection); + const firstReadyTask = getReadyForProductionTask(queues, storageOptimumFullness); + const requiredResources = getReadyTaskRequiredResources(firstReadyTask); const frontierResources = taskCollection.getFrontierResources(); const totalRequiredResources = taskCollection.getAllTasksRequiredResources(); @@ -210,16 +247,17 @@ function createVillageOwnState( village, resources, performance, - storage: calcStorageBalance(resources, Resources.fromStorage(resourceStorage), performance), - required: calcResourceBalance(requiredResources, resources, performance), + storage: makeStorageBalance(resources, storageResources, performance), + required: makeResourceBalance(requiredResources, resources, performance), upperCriticalLevel, storageOptimumFullness, isOverflowing, - frontierRequired: calcResourceBalance(frontierResources, resources, performance), - totalRequired: calcResourceBalance(totalRequiredResources, resources, performance), + queues, + firstReadyTask, + frontierRequired: makeResourceBalance(frontierResources, resources, performance), + totalRequired: makeResourceBalance(totalRequiredResources, resources, performance), incomingResources: calcIncomingResources(storage), settings: storage.getSettings(), - queues: createAllProductionQueueStates(storage, taskCollection), }; } diff --git a/src/VillageTaskCollection.ts b/src/VillageTaskCollection.ts index 2f9f4fc..b06041a 100644 --- a/src/VillageTaskCollection.ts +++ b/src/VillageTaskCollection.ts @@ -8,9 +8,8 @@ import { ContractAttributes, ContractType } from './Core/Contract'; import { UpgradeBuildingTask } from './Task/UpgradeBuildingTask'; import { ForgeImprovementTask } from './Task/ForgeImprovementTask'; import * as _ from 'underscore'; -import { TrainTroopTask } from './Task/TrainTroopTask'; -interface QueueTasks { +export interface QueueTasks { queue: ProductionQueue; tasks: Array; finishTs: number; @@ -61,7 +60,7 @@ export class VillageTaskCollection { this.removeTasks(t => t.id === taskId); } - private getQueueGroupedTasks(): Array { + getQueueGroupedTasks(): Array { const tasks = this.storage.getTasks(); const result: Array = []; for (let queue of OrderedProductionQueues) { @@ -74,28 +73,6 @@ export class VillageTaskCollection { return result; } - getTasksInProductionQueue(queue: ProductionQueue): Array { - return this.storage.getTasks().filter(isInQueue(queue)); - } - - getReadyForProductionTask(): Task | undefined { - const groups = this.getQueueGroupedTasks(); - const nowTs = timestamp(); - const firstReadyGroup = groups.find(g => g.finishTs <= nowTs && g.tasks.length !== 0); - if (!firstReadyGroup) { - return undefined; - } - - const maxCapacity = Resources.fromStorage(this.storage.getResourceStorage()); - - return firstReadyGroup.tasks.find( - t => - t.name === TrainTroopTask.name || - !t.args.resources || - maxCapacity.allGreaterOrEqual(Resources.fromObject(t.args.resources)) - ); - } - postponeTask(taskId: TaskId, seconds: number) { const modifyTime = withTime(timestamp() + seconds); this.modifyTasks(task => task.id === taskId, modifyTime); @@ -116,14 +93,6 @@ export class VillageTaskCollection { } } - getReadyTaskRequiredResources(): Resources { - const first = this.getReadyForProductionTask(); - if (first && first.args.resources) { - return Resources.fromObject(first.args.resources); - } - return Resources.zero(); - } - getFrontierResources(): Resources { let result = Resources.zero(); const groups = this.getQueueGroupedTasks();