Improve hero balance with commitments

This commit is contained in:
Anton Vakhrushev 2020-05-02 10:51:00 +03:00
parent 9f17ed2bc3
commit bacedb0d84
3 changed files with 46 additions and 75 deletions

View File

@ -1,31 +1,47 @@
import { ActionController, registerAction } from './ActionController'; import { ActionController, registerAction } from './ActionController';
import { grabVillageResources, grabVillageResourceStorage } from '../Page/ResourcesBlock'; import { grabVillageResources, grabVillageResourceStorage } from '../Page/ResourcesBlock';
import { changeHeroResource, grabCurrentHeroResource } from '../Page/HeroPage'; import { changeHeroResource, grabCurrentHeroResource } from '../Page/HeroPage';
import { grabActiveVillageId } from '../Page/VillageBlock'; import { grabActiveVillageId, grabVillageList } from '../Page/VillageBlock';
import { HeroStorage } from '../Storage/HeroStorage'; import { HeroStorage } from '../Storage/HeroStorage';
import { calcHeroResource } from '../Core/HeroBalance'; import { calcHeroResource } from '../Core/HeroBalance';
import { HeroAllResources } from '../Core/Hero'; import { HeroAllResources } from '../Core/Hero';
import { Args } from '../Queue/Args'; import { Args } from '../Queue/Args';
import { Task } from '../Queue/TaskProvider'; import { Task } from '../Queue/TaskProvider';
import { Resources } from '../Core/Resources';
import { createVillageStates } from '../VillageState';
import { ActionError } from '../Errors';
@registerAction @registerAction
export class BalanceHeroResourcesAction extends ActionController { export class BalanceHeroResourcesAction extends ActionController {
async run(args: Args, task: Task): Promise<any> { async run(args: Args, task: Task): Promise<any> {
const activeVillageId = grabActiveVillageId(); const thisVillageId = grabActiveVillageId();
const heroVillageId = new HeroStorage().getVillageId(); const heroVillageId = new HeroStorage().getVillageId();
if (heroVillageId === undefined || activeVillageId !== heroVillageId) { if (heroVillageId === undefined || heroVillageId !== thisVillageId) {
changeHeroResource(HeroAllResources); changeHeroResource(HeroAllResources);
return; return;
} }
const resources = grabVillageResources(); const villages = grabVillageList();
const requiredResources = this.scheduler.getVillageRequiredResources(heroVillageId); const villageStates = createVillageStates(villages, this.scheduler);
const totalRequiredResources = this.scheduler.getTotalVillageRequiredResources(heroVillageId); const thisVillageState = villageStates.find(s => s.id === thisVillageId);
const storage = grabVillageResourceStorage();
const currentType = grabCurrentHeroResource();
const heroType = calcHeroResource(resources, requiredResources, totalRequiredResources, storage); if (!thisVillageState) {
throw new ActionError(`State for village ${thisVillageId} not found`);
}
const requirements = [
thisVillageState.required.balance,
thisVillageState.commitments,
thisVillageState.totalRequired.balance,
thisVillageState.resources.sub(thisVillageState.storage),
];
console.log('Requirements');
console.table(requirements);
const heroType = calcHeroResource(requirements);
const currentType = grabCurrentHeroResource();
if (heroType !== currentType) { if (heroType !== currentType) {
changeHeroResource(heroType); changeHeroResource(heroType);

View File

@ -1,39 +1,27 @@
import { Resources } from './Resources'; import { Resources } from './Resources';
import { ResourceStorage } from './ResourceStorage';
import { HeroAllResources, HeroResourceType } from './Hero'; import { HeroAllResources, HeroResourceType } from './Hero';
export function calcHeroResource( export function calcHeroResource(requirements: ReadonlyArray<Resources>): HeroResourceType {
current: Resources, const resourceDiff = getFirstRequirement(requirements);
required: Resources,
totalRequired: Resources,
storage: ResourceStorage
): HeroResourceType {
const resourceDiff = calcNeedResources(current, required, totalRequired, storage);
const resourcesAsList = resourceDiff.asList(); const resourcesAsList = resourceDiff.asList();
const sorted = resourcesAsList.sort((x, y) => y.value - x.value); const sorted = resourcesAsList.sort((x, y) => x.value - y.value);
const maxRequirement = sorted[0]; const maxRequirement = sorted[0];
const minRequirement = sorted[sorted.length - 1]; const minRequirement = sorted[sorted.length - 1];
const delta = maxRequirement.value - minRequirement.value;
const eps = maxRequirement.value / 10; const delta = Math.abs(maxRequirement.value - minRequirement.value);
const eps = Math.abs(maxRequirement.value / 10);
return delta > eps ? maxRequirement.type : HeroAllResources; return delta > eps ? maxRequirement.type : HeroAllResources;
} }
function calcNeedResources( function getFirstRequirement(requirements: ReadonlyArray<Resources>): Resources {
current: Resources, for (let required of requirements) {
required: Resources, if (required.lt(Resources.zero())) {
totalRequired: Resources, return required;
storage: ResourceStorage }
): Resources {
if (current.lt(required)) {
return required.sub(current);
} }
if (current.lt(totalRequired)) { return Resources.zero();
return totalRequired.sub(current);
}
return Resources.fromStorage(storage).sub(current);
} }

View File

@ -4,51 +4,18 @@ import { expect } from 'chai';
import { calcHeroResource } from '../../src/Core/HeroBalance'; import { calcHeroResource } from '../../src/Core/HeroBalance';
import { Resources } from '../../src/Core/Resources'; import { Resources } from '../../src/Core/Resources';
import { ResourceType } from '../../src/Core/ResourceType'; import { ResourceType } from '../../src/Core/ResourceType';
import { ResourceStorage } from '../../src/Core/ResourceStorage';
describe('HeroBalance', function() { describe('HeroBalance', function() {
it('Get resource for requirement', function() { it('Get resource for single requirement', function() {
const current = new Resources(100, 100, 100, 100); const req = new Resources(0, 0, -100, 0);
const required = new Resources(200, 200, 400, 300); const heroRes = calcHeroResource([req]);
const totalRequired = new Resources(200, 200, 400, 300); expect(heroRes).to.equals(ResourceType.Iron);
const storage = new ResourceStorage(1000, 1000);
const heroRes = calcHeroResource(current, required, totalRequired, storage);
expect(ResourceType.Iron).to.equals(heroRes);
}); });
it('Get resource if one is enough, others non equal', function() { it('Get resource for second requirement', function() {
const current = new Resources(100, 100, 100, 500); const req1 = new Resources(0, 0, 100, 0);
const required = new Resources(200, 200, 400, 300); const req2 = new Resources(0, -200, 20, 0);
const totalRequired = new Resources(200, 200, 400, 300); const heroRes = calcHeroResource([req1, req2]);
const storage = new ResourceStorage(1000, 1000); expect(heroRes).to.equals(ResourceType.Clay);
const heroRes = calcHeroResource(current, required, totalRequired, storage);
expect(ResourceType.Iron).to.equals(heroRes);
});
it('Get resource if one is enough, others three equal', function() {
const current = new Resources(100, 100, 100, 500);
const required = new Resources(400, 400, 400, 300);
const totalRequired = new Resources(400, 400, 400, 300);
const storage = new ResourceStorage(1000, 1000);
const heroRes = calcHeroResource(current, required, totalRequired, storage);
expect(ResourceType.Lumber).to.equals(heroRes);
});
it('Get resource if all are enough, but storage non optimal', function() {
const current = new Resources(500, 400, 300, 600);
const required = new Resources(100, 100, 100, 100);
const totalRequired = new Resources(100, 100, 100, 100);
const storage = new ResourceStorage(1000, 1000);
const heroRes = calcHeroResource(current, required, totalRequired, storage);
expect(ResourceType.Iron).to.equals(heroRes);
});
it('Get resource if enough, but total not enough', function() {
const current = new Resources(300, 300, 300, 300);
const required = new Resources(100, 100, 100, 100);
const totalRequired = new Resources(500, 600, 200, 200);
const storage = new ResourceStorage(1000, 1000);
const heroRes = calcHeroResource(current, required, totalRequired, storage);
expect(ResourceType.Clay).to.equals(heroRes);
}); });
}); });