Mark tasks with required warehouse extra capacity

This commit is contained in:
Anton Vakhrushev 2020-06-28 20:29:56 +03:00
parent e2f9840dc8
commit a163d36b93
5 changed files with 68 additions and 51 deletions

View File

@ -29,32 +29,32 @@
<td class="right">
<filling
:value="villageState.resources.lumber"
:warning="villageState.storageOptimumFullness.lumber"
:critical="villageState.storageCriticalFullness.lumber"
:warning="villageState.storage.optimumFullness.lumber"
:critical="villageState.storage.criticalFullness.lumber"
:full="villageState.storage.capacity.lumber"
></filling>
</td>
<td class="right">
<filling
:value="villageState.resources.clay"
:warning="villageState.storageOptimumFullness.clay"
:critical="villageState.storageCriticalFullness.clay"
:warning="villageState.storage.optimumFullness.clay"
:critical="villageState.storage.criticalFullness.clay"
:full="villageState.storage.capacity.clay"
></filling>
</td>
<td class="right">
<filling
:value="villageState.resources.iron"
:warning="villageState.storageOptimumFullness.iron"
:critical="villageState.storageCriticalFullness.iron"
:warning="villageState.storage.optimumFullness.iron"
:critical="villageState.storage.criticalFullness.iron"
:full="villageState.storage.capacity.iron"
></filling>
</td>
<td class="right">
<filling
:value="villageState.resources.crop"
:warning="villageState.storageOptimumFullness.crop"
:critical="villageState.storageCriticalFullness.crop"
:warning="villageState.storage.optimumFullness.crop"
:critical="villageState.storage.criticalFullness.crop"
:full="villageState.storage.capacity.crop"
></filling>
</td>

View File

@ -1,7 +1,11 @@
<template>
<table class="task-list">
<tr v-for="task in tasks">
<td class="col-name" v-text="task.name" :title="task.name + ', ' + task.id"></td>
<td
class="col-name"
v-text="(task.canBeBuilt ? '' : '(!) ') + task.name"
:title="task.name + ', ' + task.id"
></td>
<td class="col-actions">
<a href="#" class="action" @click.prevent="upTask(task.id)" title="Поднять задачу">up</a>
<a href="#" class="action" @click.prevent="downTask(task.id)" title="Опустить задачу">dn</a>
@ -46,6 +50,7 @@ export default {
}
.col-name {
width: 20%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}

View File

@ -68,7 +68,7 @@ export class ResourceTransferCalculator {
resources: readyToTransfer,
score: {
amount: readyToTransfer.amount(),
overflow: sender.getState().isOverflowing,
overflow: sender.getState().storage.isOverflowing,
},
};
}
@ -77,7 +77,7 @@ export class ResourceTransferCalculator {
sender: VillageController,
recipient: VillageController
): [Resources, Resources] {
if (sender.getState().isOverflowing) {
if (sender.getState().storage.isOverflowing) {
return [sender.getOverflowResources(), recipient.getAvailableToReceiveResources()];
}

View File

@ -1,7 +1,7 @@
import { VillageTaskCollection } from './VillageTaskCollection';
import { Task, TaskId } from './Queue/TaskProvider';
import { TaskId } from './Queue/TaskProvider';
import { Args } from './Queue/Args';
import { VillageState } from './VillageState';
import { TaskState, VillageState } from './VillageState';
import { Resources } from './Core/Resources';
import { MerchantsInfo } from './Core/Market';
import { VillageStorage } from './Storage/VillageStorage';
@ -33,7 +33,7 @@ export class VillageController {
return this.state;
}
getReadyProductionTask(): Task | undefined {
getReadyProductionTask(): TaskState | undefined {
return this.state.firstReadyTask;
}
@ -66,7 +66,7 @@ export class VillageController {
}
getOverflowResources(): Resources {
const limit = this.state.storageOptimumFullness;
const limit = this.state.storage.optimumFullness;
const currentResources = this.state.resources;
return currentResources.sub(limit).max(Resources.zero());
@ -75,7 +75,7 @@ export class VillageController {
getFreeResources(): Resources {
const mode = this.state.settings.receiveResourcesMode;
const requirementResources = this.state.required.resources;
const optimumToStoreResources = this.state.storageOptimumFullness;
const optimumToStoreResources = this.state.storage.optimumFullness;
switch (mode) {
case ReceiveResourcesMode.Required:
@ -101,7 +101,7 @@ export class VillageController {
getRequiredResources(): Resources {
const mode = this.state.settings.receiveResourcesMode;
const optimumToStoreResources = this.state.storageOptimumFullness;
const optimumToStoreResources = this.state.storage.optimumFullness;
const requirementResources = this.state.required.resources;
switch (mode) {
@ -113,7 +113,7 @@ export class VillageController {
}
private calcRequiredResources(targetResources: Resources): Resources {
const optimumToStoreResources = this.state.storageOptimumFullness;
const optimumToStoreResources = this.state.storage.optimumFullness;
const currentResources = this.state.resources;
const incomingResources = this.state.incomingResources;
@ -125,7 +125,7 @@ export class VillageController {
}
getAvailableToReceiveResources(): Resources {
const optimumToStoreResources = this.state.storageOptimumFullness;
const optimumToStoreResources = this.state.storage.optimumFullness;
const currentResources = this.state.resources;
return optimumToStoreResources.sub(currentResources).max(Resources.zero());

View File

@ -5,10 +5,18 @@ import { calcGatheringTimings, GatheringTime } from './Core/GatheringTimings';
import { VillageRepositoryInterface } from './VillageRepository';
import { VillageNotFound } from './Errors';
import { ProductionQueue } from './Core/ProductionQueue';
import { Task } from './Queue/TaskProvider';
import { Task, TaskId } from './Queue/TaskProvider';
import { timestamp } from './utils';
import { QueueTasks, VillageTaskCollection } from './VillageTaskCollection';
import { TrainTroopTask } from './Task/TrainTroopTask';
import { Args } from './Queue/Args';
export interface TaskState {
id: TaskId;
name: string;
args: Args;
canBeBuilt: boolean;
}
interface VillageStorageState {
resources: Resources;
@ -17,6 +25,9 @@ interface VillageStorageState {
performance: Resources;
timeToZero: GatheringTime;
timeToFull: GatheringTime;
optimumFullness: Resources;
criticalFullness: Resources;
isOverflowing: boolean;
}
/**
@ -43,7 +54,7 @@ interface ResourceLineState {
interface VillageProductionQueueState {
queue: ProductionQueue;
tasks: Array<Task>;
tasks: Array<TaskState>;
isActive: boolean;
isWaiting: boolean;
currentTaskFinishTimestamp: number;
@ -68,12 +79,9 @@ interface VillageOwnState {
resources: Resources;
performance: Resources;
storage: VillageStorageState;
storageOptimumFullness: Resources;
storageCriticalFullness: Resources;
isOverflowing: boolean;
queues: Array<VillageProductionQueueState>;
tasks: Array<Task>;
firstReadyTask: Task | undefined;
tasks: Array<TaskState>;
firstReadyTask: TaskState | undefined;
/**
* Required resources for nearest task
*/
@ -111,6 +119,8 @@ function makeStorageState(
storage: Resources,
performance: Resources
): VillageStorageState {
const optimumFullness = storage.sub(performance.scale(3));
const criticalFullness = storage.sub(performance.scale(1));
return {
resources,
capacity: storage,
@ -118,6 +128,9 @@ function makeStorageState(
balance: storage.sub(resources),
timeToZero: timeToFastestResource(resources, Resources.zero(), performance),
timeToFull: timeToFastestResource(resources, storage, performance),
optimumFullness: optimumFullness,
criticalFullness: criticalFullness,
isOverflowing: criticalFullness.anyLower(resources),
};
}
@ -151,13 +164,13 @@ function taskResourceReducer(resources: Resources, task: Task) {
function createProductionQueueState(
taskQueueInfo: QueueTasks,
storage: VillageStorage
storage: VillageStorageState
): VillageProductionQueueState {
const queue = taskQueueInfo.queue;
const tasks = taskQueueInfo.tasks;
const taskEndingTimestamp = taskQueueInfo.finishTs;
const resources = storage.getResources();
const performance = storage.getResourcesPerformance();
const resources = storage.resources;
const performance = storage.performance;
const firstTaskResources = tasks.slice(0, 1).reduce(taskResourceReducer, Resources.zero());
const allTaskResources = tasks.reduce(taskResourceReducer, Resources.zero());
@ -165,7 +178,7 @@ function createProductionQueueState(
return {
queue,
tasks,
tasks: tasks.map(t => makeTaskState(t, storage.optimumFullness)),
isActive: tasks.length !== 0 || taskEndingTimestamp > currentTimestamp,
isWaiting: tasks.length !== 0 && taskEndingTimestamp < currentTimestamp,
currentTaskFinishTimestamp: taskEndingTimestamp,
@ -180,7 +193,7 @@ function createProductionQueueState(
}
function createAllProductionQueueStates(
storage: VillageStorage,
storage: VillageStorageState,
taskCollection: VillageTaskCollection
) {
let result: Array<VillageProductionQueueState> = [];
@ -191,28 +204,32 @@ function createAllProductionQueueStates(
}
function getReadyForProductionTask(
queues: ReadonlyArray<VillageProductionQueueState>,
maxResourcesForTask: Resources
): Task | undefined {
queues: ReadonlyArray<VillageProductionQueueState>
): TaskState | undefined {
const firstReadyQueue = queues.find(queue => queue.isWaiting);
if (!firstReadyQueue) {
return undefined;
}
return firstReadyQueue.tasks.find(
task =>
task.name === TrainTroopTask.name ||
maxResourcesForTask.allGreaterOrEqual(getTaskResources(task))
);
return firstReadyQueue.tasks.find(task => task.name === TrainTroopTask.name || task.canBeBuilt);
}
function getTaskResources(task: Task | undefined): Resources {
function getTaskResources(task: Task | TaskState | undefined): Resources {
if (task && task.args.resources) {
return Resources.fromObject(task.args.resources);
}
return Resources.zero();
}
function makeTaskState(task: Task, maxResourcesForTask: Resources): TaskState {
return {
id: task.id,
args: task.args,
name: task.name,
canBeBuilt: maxResourcesForTask.allGreaterOrEqual(getTaskResources(task)),
};
}
function createVillageOwnState(
village: Village,
storage: VillageStorage,
@ -222,25 +239,20 @@ function createVillageOwnState(
const resources = storage.getResources();
const storageResources = Resources.fromStorage(storage.getResourceStorage());
const performance = storage.getResourcesPerformance();
const storageOptimumFullness = storageResources.sub(performance.scale(3));
const storageCriticalFullness = storageResources.sub(performance.scale(1));
const isOverflowing = storageCriticalFullness.anyLower(resources);
const queues = createAllProductionQueueStates(storage, taskCollection);
const firstReadyTask = getReadyForProductionTask(queues, storageOptimumFullness);
const requiredResources = getTaskResources(firstReadyTask);
const storageState = makeStorageState(resources, storageResources, performance);
const queues = createAllProductionQueueStates(storageState, taskCollection);
const firstReadyTask = getReadyForProductionTask(queues);
const requiredResources = getTaskResources(firstReadyTask);
return {
id: village.id,
village,
resources,
performance,
storage: makeStorageState(resources, storageResources, performance),
storage: storageState,
required: makeResourceState(requiredResources, resources, performance),
storageOptimumFullness,
storageCriticalFullness,
isOverflowing,
queues,
tasks: taskCollection.getTasks(),
tasks: taskCollection.getTasks().map(t => makeTaskState(t, storageState.optimumFullness)),
firstReadyTask,
incomingResources: calcIncomingResources(storage),
settings,