Fix hero balance
Add tests for checking
This commit is contained in:
parent
ea4d6f6681
commit
57e79b0ba2
5
.mocharc.json
Normal file
5
.mocharc.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"extension": ["ts"],
|
||||||
|
"spec": "tests/**/*.ts",
|
||||||
|
"require": "ts-node/register"
|
||||||
|
}
|
2
Makefile
2
Makefile
@ -1,4 +1,4 @@
|
|||||||
all: format build
|
all: test format build
|
||||||
|
|
||||||
restart-server:
|
restart-server:
|
||||||
docker-compose restart
|
docker-compose restart
|
||||||
|
20
package-lock.json
generated
20
package-lock.json
generated
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "@anwinged/predictor",
|
"name": "@anwinged/travian",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
@ -47,9 +47,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"json5": {
|
"json5": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/json5/-/json5-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz",
|
||||||
"integrity": "sha512-MoUOQ4WdiN3yxhm7NEVJSJrieAo5hNSLQ5sj05OTRHPL9HOBy8u4Bu88jsC1jvqAdN+E1bJmsUcZH+1HQxliqQ==",
|
"integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"minimist": "^1.2.5"
|
"minimist": "^1.2.5"
|
||||||
@ -175,9 +175,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@babel/helpers": {
|
"@babel/helpers": {
|
||||||
"version": "7.9.0",
|
"version": "7.9.2",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.9.2.tgz",
|
||||||
"integrity": "sha512-/9GvfYTCG1NWCNwDj9e+XlnSCmWW/r9T794Xi58vPF9WCcnZCAZ0kWLSn54oqP40SUvh1T2G6VwKmFO5AOlW3A==",
|
"integrity": "sha512-JwLvzlXVPjO8eU9c/wF9/zOIN7X6h8DYf7mG4CiFRZRvZNKEF5dQ3H3V+ASkHoIB3mWhatgl5ONhyqHRI6MppA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/template": "^7.8.3",
|
"@babel/template": "^7.8.3",
|
||||||
@ -5152,9 +5152,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"resolve": {
|
"resolve": {
|
||||||
"version": "1.15.1",
|
"version": "1.16.1",
|
||||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz",
|
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.16.1.tgz",
|
||||||
"integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==",
|
"integrity": "sha512-rmAglCSqWWMrrBv/XM6sW0NuRFiKViw/W4d9EbC4pt+49H8JwHy+mcGmALTEg504AUDcLTvb1T2q3E9AnmY+ig==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"path-parse": "^1.0.6"
|
"path-parse": "^1.0.6"
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
{
|
{
|
||||||
"name": "@anwinged/predictor",
|
"name": "@anwinged/travian",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"author": "Anton Vakhrushev",
|
"author": "Anton Vakhrushev",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"main": "dist/predictor.js",
|
"main": "dist/travian.js",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/anwinged/predictor.git"
|
"url": "https://github.com/anwinged/travian.git"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "mocha",
|
"test": "mocha",
|
||||||
|
@ -3,9 +3,10 @@ import { Args } from '../Command';
|
|||||||
import { Task } from '../Queue/TaskQueue';
|
import { Task } from '../Queue/TaskQueue';
|
||||||
import { grabResources, grabResourceStorage } from '../Page/ResourcesBlock';
|
import { grabResources, grabResourceStorage } from '../Page/ResourcesBlock';
|
||||||
import { changeHeroResource, grabCurrentHeroResource } from '../Page/HeroPage';
|
import { changeHeroResource, grabCurrentHeroResource } from '../Page/HeroPage';
|
||||||
import { HeroAllResources, Resources } from '../Game';
|
import { HeroAllResources } from '../Game';
|
||||||
import { grabActiveVillageId } from '../Page/VillageBlock';
|
import { grabActiveVillageId } from '../Page/VillageBlock';
|
||||||
import { HeroState } from '../State/HeroState';
|
import { HeroState } from '../State/HeroState';
|
||||||
|
import { Core } from '../Core/HeroBalance';
|
||||||
|
|
||||||
@registerAction
|
@registerAction
|
||||||
export class BalanceHeroResourcesAction extends ActionController {
|
export class BalanceHeroResourcesAction extends ActionController {
|
||||||
@ -18,40 +19,16 @@ export class BalanceHeroResourcesAction extends ActionController {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const resources = this.getRequirements(heroVillageId);
|
|
||||||
|
|
||||||
const resourcesAsList = resources.asList();
|
|
||||||
const currentType = grabCurrentHeroResource();
|
|
||||||
|
|
||||||
const sorted = resourcesAsList.sort((x, y) => y.value - x.value);
|
|
||||||
const maxRequirement = sorted[0];
|
|
||||||
const minRequirement = sorted[sorted.length - 1];
|
|
||||||
const delta = Math.abs(maxRequirement.value - minRequirement.value);
|
|
||||||
const eps = Math.abs(maxRequirement.value / 10);
|
|
||||||
|
|
||||||
console.log('REQUIREMENTS', sorted);
|
|
||||||
console.log('REQUIREMENTS', maxRequirement, minRequirement, delta, eps);
|
|
||||||
|
|
||||||
const resType = delta > eps ? maxRequirement.type : HeroAllResources;
|
|
||||||
if (resType !== currentType) {
|
|
||||||
changeHeroResource(resType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private getRequirements(heroVillageId): Resources {
|
|
||||||
const resources = grabResources();
|
const resources = grabResources();
|
||||||
const requiredResources = this.scheduler.getVillageRequiredResources(heroVillageId);
|
const requiredResources = this.scheduler.getVillageRequiredResources(heroVillageId);
|
||||||
const totalRequiredResources = this.scheduler.getTotalVillageRequiredResources(heroVillageId);
|
const totalRequiredResources = this.scheduler.getTotalVillageRequiredResources(heroVillageId);
|
||||||
|
|
||||||
if (requiredResources.gt(resources)) {
|
|
||||||
return requiredResources.sub(resources);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (totalRequiredResources.gt(resources)) {
|
|
||||||
return totalRequiredResources.sub(resources);
|
|
||||||
}
|
|
||||||
|
|
||||||
const storage = grabResourceStorage();
|
const storage = grabResourceStorage();
|
||||||
return Resources.fromStorage(storage).sub(resources);
|
const currentType = grabCurrentHeroResource();
|
||||||
|
|
||||||
|
const heroType = Core.calcHeroResource(resources, requiredResources, totalRequiredResources, storage);
|
||||||
|
|
||||||
|
if (heroType !== currentType) {
|
||||||
|
changeHeroResource(heroType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
43
src/Core/HeroBalance.ts
Normal file
43
src/Core/HeroBalance.ts
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import { HeroAllResources, HeroResourceType, Resources, ResourceStorage } from '../Game';
|
||||||
|
|
||||||
|
export namespace Core {
|
||||||
|
export function calcHeroResource(
|
||||||
|
current: Resources,
|
||||||
|
required: Resources,
|
||||||
|
totalRequired: Resources,
|
||||||
|
storage: ResourceStorage
|
||||||
|
): HeroResourceType {
|
||||||
|
const resourceDiff = calcNeedResources(current, required, totalRequired, storage);
|
||||||
|
const resourcesAsList = resourceDiff.asList();
|
||||||
|
|
||||||
|
const sorted = resourcesAsList.filter(x => x.value > 0).sort((x, y) => y.value - x.value);
|
||||||
|
|
||||||
|
if (sorted.length === 0) {
|
||||||
|
return HeroAllResources;
|
||||||
|
}
|
||||||
|
|
||||||
|
const maxRequirement = sorted[0];
|
||||||
|
const minRequirement = sorted[sorted.length - 1];
|
||||||
|
const delta = maxRequirement.value - minRequirement.value;
|
||||||
|
const eps = maxRequirement.value / 10;
|
||||||
|
|
||||||
|
return delta > eps ? maxRequirement.type : HeroAllResources;
|
||||||
|
}
|
||||||
|
|
||||||
|
function calcNeedResources(
|
||||||
|
current: Resources,
|
||||||
|
required: Resources,
|
||||||
|
totalRequired: Resources,
|
||||||
|
storage: ResourceStorage
|
||||||
|
): Resources {
|
||||||
|
if (!current.gt(required)) {
|
||||||
|
return required.sub(current);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!current.gt(totalRequired)) {
|
||||||
|
return totalRequired.sub(current);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Resources.fromStorage(storage).sub(current);
|
||||||
|
}
|
||||||
|
}
|
34
tests/Core/HeroBalanceTest.ts
Normal file
34
tests/Core/HeroBalanceTest.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import { it, describe } from 'mocha';
|
||||||
|
import { expect } from 'chai';
|
||||||
|
|
||||||
|
import { Resources, ResourceStorage, ResourceType } from '../../src/Game';
|
||||||
|
import { Core } from '../../src/Core/HeroBalance';
|
||||||
|
|
||||||
|
describe('HeroBalance', function() {
|
||||||
|
it('Get resource for requirement', function() {
|
||||||
|
const current = new Resources(100, 100, 100, 100);
|
||||||
|
const required = new Resources(200, 200, 400, 300);
|
||||||
|
const totalRequired = new Resources(200, 200, 400, 300);
|
||||||
|
const storage = new ResourceStorage(1000, 1000);
|
||||||
|
const heroRes = Core.calcHeroResource(current, required, totalRequired, storage);
|
||||||
|
expect(heroRes).to.equals(ResourceType.Iron);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Get resource if one is enough', function() {
|
||||||
|
const current = new Resources(100, 100, 100, 500);
|
||||||
|
const required = new Resources(200, 200, 400, 300);
|
||||||
|
const totalRequired = new Resources(200, 200, 400, 300);
|
||||||
|
const storage = new ResourceStorage(1000, 1000);
|
||||||
|
const heroRes = Core.calcHeroResource(current, required, totalRequired, storage);
|
||||||
|
expect(heroRes).to.equals(ResourceType.Iron);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Get resource if all are enough, but storage non optimal', function() {
|
||||||
|
const current = new Resources(600, 600, 500, 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 = Core.calcHeroResource(current, required, totalRequired, storage);
|
||||||
|
expect(heroRes).to.equals(ResourceType.Iron);
|
||||||
|
});
|
||||||
|
});
|
@ -3,7 +3,7 @@
|
|||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"experimentalDecorators": true,
|
"experimentalDecorators": true,
|
||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
"module": "es2015",
|
"module": "commonjs",
|
||||||
"outDir": "./dist",
|
"outDir": "./dist",
|
||||||
"strictNullChecks": true,
|
"strictNullChecks": true,
|
||||||
"strictPropertyInitialization": true,
|
"strictPropertyInitialization": true,
|
||||||
|
Loading…
Reference in New Issue
Block a user