Improve send resources task
This commit is contained in:
parent
d1a2128411
commit
c5de5ca901
@ -1,27 +1,30 @@
|
|||||||
import { ActionController, taskError, registerAction } from './ActionController';
|
import { ActionController, taskError, registerAction } from './ActionController';
|
||||||
import { AbortTaskError, TryLaterError } from '../Errors';
|
import { TryLaterError } from '../Errors';
|
||||||
import { Resources } from '../Core/Resources';
|
import { Resources } from '../Core/Resources';
|
||||||
import { Coordinates, Village } from '../Core/Village';
|
import { Coordinates } from '../Core/Village';
|
||||||
import { grabVillageResources } from '../Page/ResourcesBlock';
|
|
||||||
import { grabActiveVillageId, grabVillageList } from '../Page/VillageBlock';
|
|
||||||
import { aroundMinutes, timestamp } from '../utils';
|
import { aroundMinutes, timestamp } from '../utils';
|
||||||
import { VillageStorage } from '../Storage/VillageStorage';
|
|
||||||
import { Args } from '../Queue/Args';
|
import { Args } from '../Queue/Args';
|
||||||
import { Task } from '../Queue/TaskProvider';
|
import { Task } from '../Queue/TaskProvider';
|
||||||
import { clickSendButton, fillSendResourcesForm, grabMerchantsInfo } from '../Page/BuildingPage/MarketPage';
|
import { clickSendButton, fillSendResourcesForm, grabMerchantsInfo } from '../Page/BuildingPage/MarketPage';
|
||||||
|
import { VillageState } from '../VillageState';
|
||||||
|
|
||||||
const TIMEOUT = 15;
|
const TIMEOUT = 15;
|
||||||
|
const AMOUNT_THRESHOLD = 100;
|
||||||
|
|
||||||
@registerAction
|
@registerAction
|
||||||
export class SendResourcesAction extends ActionController {
|
export class SendResourcesAction extends ActionController {
|
||||||
async run(args: Args, task: Task): Promise<any> {
|
async run(args: Args, task: Task): Promise<any> {
|
||||||
|
this.ensureSameVillage(args, task);
|
||||||
|
|
||||||
|
const senderVillageId = args.villageId || taskError('No source village id');
|
||||||
|
const targetVillageId = args.targetVillageId || taskError('No target village id');
|
||||||
|
|
||||||
const coordinates = Coordinates.fromObject(args.coordinates || taskError('No coordinates'));
|
const coordinates = Coordinates.fromObject(args.coordinates || taskError('No coordinates'));
|
||||||
|
|
||||||
const recipientVillage = args.targetVillageId
|
const senderVillage = this.villageStateRepository.getVillageState(senderVillageId);
|
||||||
? this.findRecipientVillageById(args.targetVillageId)
|
const recipientVillage = this.villageStateRepository.getVillageState(targetVillageId);
|
||||||
: this.findRecipientVillage(coordinates);
|
|
||||||
|
|
||||||
const readyToTransfer = this.getResourcesForTransfer(recipientVillage.id);
|
const readyToTransfer = this.getResourcesForTransfer(senderVillage, recipientVillage);
|
||||||
|
|
||||||
console.log('To transfer res', readyToTransfer);
|
console.log('To transfer res', readyToTransfer);
|
||||||
|
|
||||||
@ -32,24 +35,6 @@ export class SendResourcesAction extends ActionController {
|
|||||||
clickSendButton();
|
clickSendButton();
|
||||||
}
|
}
|
||||||
|
|
||||||
private findRecipientVillageById(villageId: number): Village {
|
|
||||||
const villageList = grabVillageList();
|
|
||||||
const village = villageList.find(v => v.id === villageId);
|
|
||||||
if (!village) {
|
|
||||||
throw new AbortTaskError('No village');
|
|
||||||
}
|
|
||||||
return village;
|
|
||||||
}
|
|
||||||
|
|
||||||
private findRecipientVillage(coordinates: Coordinates): Village {
|
|
||||||
const villageList = grabVillageList();
|
|
||||||
const village = villageList.find(v => v.crd.eq(coordinates));
|
|
||||||
if (!village) {
|
|
||||||
throw new AbortTaskError('No village');
|
|
||||||
}
|
|
||||||
return village;
|
|
||||||
}
|
|
||||||
|
|
||||||
private getMerchantsCapacity(): number {
|
private getMerchantsCapacity(): number {
|
||||||
const merchants = grabMerchantsInfo();
|
const merchants = grabMerchantsInfo();
|
||||||
const capacity = merchants.available * merchants.carry;
|
const capacity = merchants.available * merchants.carry;
|
||||||
@ -59,55 +44,67 @@ export class SendResourcesAction extends ActionController {
|
|||||||
return capacity;
|
return capacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
private getSenderAvailableResources(): Resources {
|
private getSenderAvailableResources(senderState: VillageState): Resources {
|
||||||
const villageId = grabActiveVillageId();
|
const balance = senderState.required.balance;
|
||||||
const resources = grabVillageResources();
|
const free = balance.max(Resources.zero());
|
||||||
const requirements = this.scheduler.getVillageRequiredResources(villageId);
|
|
||||||
const free = resources.sub(requirements).max(Resources.zero());
|
console.table([
|
||||||
console.log('Sender res', resources);
|
{ name: 'Sender balance', ...balance },
|
||||||
console.log('Sender req', requirements);
|
{ name: 'Sender free', ...free },
|
||||||
console.log('Sender free', free);
|
]);
|
||||||
if (free.amount() < 100) {
|
|
||||||
|
if (free.amount() < AMOUNT_THRESHOLD) {
|
||||||
throw new TryLaterError(aroundMinutes(TIMEOUT), 'Little free resources');
|
throw new TryLaterError(aroundMinutes(TIMEOUT), 'Little free resources');
|
||||||
}
|
}
|
||||||
return free;
|
return free;
|
||||||
}
|
}
|
||||||
|
|
||||||
private getRecipientRequirements(villageId: number): Resources {
|
private getRecipientRequirements(recipientState: VillageState): Resources {
|
||||||
const state = new VillageStorage(villageId);
|
const maxPossibleToStore = recipientState.storage.sub(recipientState.performance);
|
||||||
const resources = state.getResources();
|
const currentResources = recipientState.resources;
|
||||||
const incoming = state.getIncomingMerchants().reduce((m, i) => m.add(i.resources), Resources.zero());
|
const incomingResources = recipientState.incomingResources;
|
||||||
const requirements = this.scheduler.getVillageRequiredResources(villageId);
|
const requirementResources = recipientState.required.resources;
|
||||||
const missing = requirements
|
const missingResources = requirementResources
|
||||||
.sub(incoming)
|
.min(maxPossibleToStore)
|
||||||
.sub(resources)
|
.sub(incomingResources)
|
||||||
|
.sub(currentResources)
|
||||||
.max(Resources.zero());
|
.max(Resources.zero());
|
||||||
console.log('Recipient res', resources);
|
|
||||||
console.log('Recipient incoming', incoming);
|
console.table([
|
||||||
console.log('Recipient req', requirements);
|
{ name: 'Recipient max possible', ...maxPossibleToStore },
|
||||||
console.log('Recipient missing', missing);
|
{ name: 'Recipient resources', ...currentResources },
|
||||||
if (missing.empty()) {
|
{ name: 'Recipient incoming', ...incomingResources },
|
||||||
|
{ name: 'Recipient requirements', ...requirementResources },
|
||||||
|
{ name: 'Recipient missing', ...missingResources },
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (missingResources.empty()) {
|
||||||
throw new TryLaterError(aroundMinutes(TIMEOUT), 'No missing resources');
|
throw new TryLaterError(aroundMinutes(TIMEOUT), 'No missing resources');
|
||||||
}
|
}
|
||||||
return missing;
|
|
||||||
|
return missingResources;
|
||||||
}
|
}
|
||||||
|
|
||||||
private getResourcesForTransfer(recipientVillageId: number): Resources {
|
private getResourcesForTransfer(senderState: VillageState, recipientState: VillageState): Resources {
|
||||||
const senderResources = this.getSenderAvailableResources();
|
const senderReadySendResources = this.getSenderAvailableResources(senderState);
|
||||||
const recipientNeeds = this.getRecipientRequirements(recipientVillageId);
|
const recipientNeedsResources = this.getRecipientRequirements(recipientState);
|
||||||
const prepared = senderResources.min(recipientNeeds);
|
const contractResources = senderReadySendResources.min(recipientNeedsResources);
|
||||||
const capacity = this.getMerchantsCapacity();
|
const merchantsCapacity = this.getMerchantsCapacity();
|
||||||
|
|
||||||
let readyToTransfer = prepared;
|
let readyToTransfer = contractResources;
|
||||||
if (prepared.amount() > capacity) {
|
if (contractResources.amount() > merchantsCapacity) {
|
||||||
readyToTransfer = prepared.scale(capacity / prepared.amount());
|
const merchantScale = merchantsCapacity / contractResources.amount();
|
||||||
|
readyToTransfer = contractResources.scale(merchantScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Sender', senderResources);
|
console.log('Merchants capacity', merchantsCapacity);
|
||||||
console.log('Recipient', recipientNeeds);
|
|
||||||
console.log('Prepared', prepared);
|
console.table([
|
||||||
console.log('Capacity', capacity);
|
{ name: 'Sender', ...senderReadySendResources },
|
||||||
console.log('Ready to transfer', readyToTransfer);
|
{ name: 'Recipient', ...recipientNeedsResources },
|
||||||
|
{ name: 'Prepared', ...contractResources },
|
||||||
|
{ name: 'Ready to transfer', ...readyToTransfer },
|
||||||
|
]);
|
||||||
|
|
||||||
return readyToTransfer;
|
return readyToTransfer;
|
||||||
}
|
}
|
||||||
|
@ -16,14 +16,32 @@ interface StorageBalance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface RequiredResources {
|
interface RequiredResources {
|
||||||
|
/**
|
||||||
|
* Required resources (always positive)
|
||||||
|
*/
|
||||||
resources: Resources;
|
resources: Resources;
|
||||||
|
/**
|
||||||
|
* Balance resources (current - required), may be negative
|
||||||
|
*/
|
||||||
balance: Resources;
|
balance: Resources;
|
||||||
|
/**
|
||||||
|
* Time to gather all type of resources (slowest time)
|
||||||
|
*/
|
||||||
time: GatheringTime;
|
time: GatheringTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface VillageOwnState {
|
interface VillageOwnState {
|
||||||
|
/**
|
||||||
|
* Village id
|
||||||
|
*/
|
||||||
id: number;
|
id: number;
|
||||||
|
/**
|
||||||
|
* Village object
|
||||||
|
*/
|
||||||
village: Village;
|
village: Village;
|
||||||
|
/**
|
||||||
|
* Current village resources
|
||||||
|
*/
|
||||||
resources: Resources;
|
resources: Resources;
|
||||||
performance: Resources;
|
performance: Resources;
|
||||||
storage: Resources;
|
storage: Resources;
|
||||||
|
Loading…
Reference in New Issue
Block a user