Reformat code

This commit is contained in:
Anton Vakhrushev 2020-05-26 22:29:41 +03:00
parent 3c118341d3
commit f69a6e629b
33 changed files with 288 additions and 74 deletions

View File

@ -15,10 +15,10 @@
"coverage": "nyc mocha",
"build:dev": "webpack",
"build": "webpack --env.production",
"format": "prettier --tab-width=4 --print-width 120 --single-quote --trailing-comma es5 --quote-props consistent --write '{src,tests}/**/*.{ts,js}'",
"format-check": "prettier --tab-width=4 --print-width 120 --single-quote --trailing-comma es5 --quote-props consistent --check '{src,tests}/**/*.{ts,js}'",
"format-vue": "prettier --tab-width=2 --print-width 120 --single-quote --trailing-comma es5 --quote-props consistent --write '{src,tests}/**/*.vue'",
"format-wp": "prettier --tab-width=4 --print-width 120 --single-quote --trailing-comma es5 --quote-props consistent --write 'webpack.config.js'"
"format": "prettier --tab-width=4 --print-width 100 --single-quote --trailing-comma es5 --quote-props consistent --write '{src,tests}/**/*.{ts,js}'",
"format-check": "prettier --tab-width=4 --print-width 100 --single-quote --trailing-comma es5 --quote-props consistent --check '{src,tests}/**/*.{ts,js}'",
"format-vue": "prettier --tab-width=2 --print-width 100 --single-quote --trailing-comma es5 --quote-props consistent --write '{src,tests}/**/*.vue'",
"format-wp": "prettier --tab-width=4 --print-width 100 --single-quote --trailing-comma es5 --quote-props consistent --write 'webpack.config.js'"
},
"devDependencies": {
"@types/chai": "^4.2.11",

View File

@ -40,7 +40,11 @@ export class FindSendResourcesPath extends ActionController {
const storage = new ResourceTransferStorage();
storage.storeReport(bestReport);
const marketPath = path('/build.php', { newdid: bestReport.fromVillageId, gid: MARKET_ID, t: 5 });
const marketPath = path('/build.php', {
newdid: bestReport.fromVillageId,
gid: MARKET_ID,
t: 5,
});
window.location.assign(marketPath);
}
}

View File

@ -3,7 +3,11 @@ import { taskError, TryLaterError } from '../Errors';
import { aroundMinutes, randomInRange } from '../utils';
import { Args } from '../Queue/Args';
import { Task } from '../Queue/TaskProvider';
import { clickTrainButton, fillTrainCount, getAvailableCount } from '../Page/BuildingPage/TrooperPage';
import {
clickTrainButton,
fillTrainCount,
getAvailableCount,
} from '../Page/BuildingPage/TrooperPage';
import { TrainTroopTask } from '../Task/TrainTroopTask';
import { Resources } from '../Core/Resources';

View File

@ -19,7 +19,9 @@ export class UpgradeResourceToLevel extends ActionController {
const requiredLevel = getNumber(args.level);
const notUpgraded = deposits.filter(dep => !dep.underConstruction && requiredLevel > dep.level);
const notUpgraded = deposits.filter(
dep => !dep.underConstruction && requiredLevel > dep.level
);
if (notUpgraded.length === 0) {
this.scheduler.removeTask(task.id);
@ -34,11 +36,17 @@ export class UpgradeResourceToLevel extends ActionController {
const secondNotUpgraded = notUpgraded.shift();
if (firstNotUpgraded && this.isTaskNotInQueue(villageId, firstNotUpgraded)) {
this.scheduler.scheduleTask(UpgradeBuildingTask.name, { villageId, buildId: firstNotUpgraded.buildId });
this.scheduler.scheduleTask(UpgradeBuildingTask.name, {
villageId,
buildId: firstNotUpgraded.buildId,
});
}
if (secondNotUpgraded && this.isTaskNotInQueue(villageId, secondNotUpgraded)) {
this.scheduler.scheduleTask(UpgradeBuildingTask.name, { villageId, buildId: secondNotUpgraded.buildId });
this.scheduler.scheduleTask(UpgradeBuildingTask.name, {
villageId,
buildId: secondNotUpgraded.buildId,
});
}
throw new TryLaterError(aroundMinutes(10), 'Sleep for next round');

View File

@ -53,7 +53,12 @@ export class GatheringTimings {
return new GatheringTimings(factory(lumber), factory(clay), factory(iron), factory(crop));
}
constructor(lumber: GatheringTime, clay: GatheringTime, iron: GatheringTime, crop: GatheringTime) {
constructor(
lumber: GatheringTime,
clay: GatheringTime,
iron: GatheringTime,
crop: GatheringTime
) {
this.lumber = lumber;
this.clay = clay;
this.iron = iron;
@ -97,7 +102,11 @@ function calcGatheringTime(val: number, desired: number, speed: number): Gatheri
return GatheringTime.makeCounting((diff / speed) * 3600);
}
export function calcGatheringTimings(resources: Resources, desired: Resources, speed: Resources): GatheringTimings {
export function calcGatheringTimings(
resources: Resources,
desired: Resources,
speed: Resources
): GatheringTimings {
return new GatheringTimings(
calcGatheringTime(resources.lumber, desired.lumber, speed.lumber),
calcGatheringTime(resources.clay, desired.clay, speed.clay),

View File

@ -26,7 +26,12 @@ export class Resources implements ResourcesInterface {
}
static fromStorage(storage: ResourceStorage): Resources {
return new Resources(storage.warehouse, storage.warehouse, storage.warehouse, storage.granary);
return new Resources(
storage.warehouse,
storage.warehouse,
storage.warehouse,
storage.granary
);
}
static zero(): Resources {
@ -86,16 +91,29 @@ export class Resources implements ResourcesInterface {
}
anyLower(other: ResourcesInterface): boolean {
return this.lumber < other.lumber || this.clay < other.clay || this.iron < other.iron || this.crop < other.crop;
return (
this.lumber < other.lumber ||
this.clay < other.clay ||
this.iron < other.iron ||
this.crop < other.crop
);
}
allGreater(other: ResourcesInterface): boolean {
return this.lumber > other.lumber && this.clay > other.clay && this.iron > other.iron && this.crop > other.crop;
return (
this.lumber > other.lumber &&
this.clay > other.clay &&
this.iron > other.iron &&
this.crop > other.crop
);
}
allGreaterOrEqual(other: ResourcesInterface): boolean {
return (
this.lumber >= other.lumber && this.clay >= other.clay && this.iron >= other.iron && this.crop >= other.crop
this.lumber >= other.lumber &&
this.clay >= other.clay &&
this.iron >= other.iron &&
this.crop >= other.crop
);
}
@ -136,7 +154,12 @@ export class Resources implements ResourcesInterface {
return (Math.floor(v / multiplier) + 1) * multiplier;
};
return new Resources(upper(this.lumber), upper(this.clay), upper(this.iron), upper(this.crop));
return new Resources(
upper(this.lumber),
upper(this.clay),
upper(this.iron),
upper(this.crop)
);
}
downTo(multiplier: number): Resources {
@ -151,6 +174,11 @@ export class Resources implements ResourcesInterface {
return part * multiplier;
};
return new Resources(lower(this.lumber), lower(this.clay), lower(this.iron), lower(this.crop));
return new Resources(
lower(this.lumber),
lower(this.clay),
lower(this.iron),
lower(this.crop)
);
}
}

View File

@ -6,7 +6,11 @@
</h1>
<p>
<a href="#" v-on:click.prevent="pause">
pause <span v-if="shared.pauseSeconds && shared.pauseSeconds > 0" v-text="shared.pauseSeconds"></span>
pause
<span
v-if="shared.pauseSeconds && shared.pauseSeconds > 0"
v-text="shared.pauseSeconds"
></span>
</a>
<a href="#" v-on:click.prevent="toggleLogs">logs</a>
</p>

View File

@ -57,7 +57,8 @@ export function createStore(villageFactory: VillageFactory) {
state.logs = logs;
},
[Mutations.ToggleVillageEditor](state, visible?: any) {
state.views.villageEditor = visible === undefined ? !state.views.villageEditor : !!visible;
state.views.villageEditor =
visible === undefined ? !state.views.villageEditor : !!visible;
},
[Mutations.SetVillageSettings](state, settings) {
state.villageSettings = settings;
@ -90,9 +91,11 @@ export function createStore(villageFactory: VillageFactory) {
const villageName = state.villageSettings.villageName;
const newSettings: VillageSettings = {
sendResourcesThreshold:
state.villageSettings.sendResourcesThreshold || VillageSettingsDefaults.sendResourcesThreshold,
state.villageSettings.sendResourcesThreshold ||
VillageSettingsDefaults.sendResourcesThreshold,
sendResourcesTimeout:
state.villageSettings.sendResourcesTimeout || VillageSettingsDefaults.sendResourcesTimeout,
state.villageSettings.sendResourcesTimeout ||
VillageSettingsDefaults.sendResourcesTimeout,
sendResourcesMultiplier:
state.villageSettings.sendResourcesMultiplier ||
VillageSettingsDefaults.sendResourcesMultiplier,

View File

@ -9,14 +9,32 @@
</p>
<div class="container">
<table class="task-table">
<tr v-for="task in shared.taskList" class="task-item" :class="{ 'this-village': isThisVillageTask(task) }">
<td class="time-column" :title="formatDate(task.ts) + ', ' + task.id" v-text="formatDate(task.ts)"></td>
<tr
v-for="task in shared.taskList"
class="task-item"
:class="{ 'this-village': isThisVillageTask(task) }"
>
<td
class="time-column"
:title="formatDate(task.ts) + ', ' + task.id"
v-text="formatDate(task.ts)"
></td>
<td class="actions-column">
<a href="#" title="Remove task" class="remove-action" v-on:click.prevent="onRemove(task.id)">&times;</a>
<a
href="#"
title="Remove task"
class="remove-action"
v-on:click.prevent="onRemove(task.id)"
>&times;</a
>
</td>
<td class="village-column" v-text="task.args.villageId || ''"></td>
<td class="name-column" :title="task.name" v-text="task.name"></td>
<td class="args-column" :title="JSON.stringify(task.args)" v-text="JSON.stringify(task.args)"></td>
<td
class="args-column"
:title="JSON.stringify(task.args)"
v-text="JSON.stringify(task.args)"
></td>
</tr>
</table>
</div>

View File

@ -15,7 +15,11 @@
<tbody>
<template v-for="villageState in shared.villageStates">
<tr class="normal-line top-line">
<td class="right" :class="{ active: villageState.village.active }" :title="villageHint(villageState)">
<td
class="right"
:class="{ active: villageState.village.active }"
:title="villageHint(villageState)"
>
{{ villageState.village.name }}
[<a href="#" v-on:click.prevent="openEditor(villageState.id)">ред</a>]:
</td>
@ -146,12 +150,18 @@
v-if="s.id !== villageState.id"
class="village-quick-link"
:href="marketPath(villageState.village, s.village)"
:title="'Отправить ресурсы из ' + villageState.village.name + ' в ' + s.village.name"
:title="
'Отправить ресурсы из ' + villageState.village.name + ' в ' + s.village.name
"
>$->{{ s.village.name }}</a
>
<a class="village-quick-link" :href="quartersPath(villageState.village)">Казармы</a>
<a class="village-quick-link" :href="horseStablePath(villageState.village)">Конюшни</a>
<a class="village-quick-link" :href="collectionPointPath(villageState.village)">Войска</a>
<a class="village-quick-link" :href="horseStablePath(villageState.village)"
>Конюшни</a
>
<a class="village-quick-link" :href="collectionPointPath(villageState.village)"
>Войска</a
>
</td>
</tr>

View File

@ -1,5 +1,12 @@
import { markPage, sleepMicro, timestamp, waitForLoad } from './utils';
import { AbortTaskError, ActionError, FailTaskError, GrabError, TryLaterError, VillageNotFound } from './Errors';
import {
AbortTaskError,
ActionError,
FailTaskError,
GrabError,
TryLaterError,
VillageNotFound,
} from './Errors';
import { TaskQueueRenderer } from './TaskQueueRenderer';
import { createActionHandler } from './Action/ActionController';
import { Logger } from './Logger';

View File

@ -30,6 +30,9 @@ export class ForgePageGrabber extends Grabber {
private grabTimer(): void {
const seconds = grabRemainingSeconds();
this.storage.storeQueueTaskEnding(ProductionQueue.UpgradeUnit, seconds ? seconds + timestamp() : 0);
this.storage.storeQueueTaskEnding(
ProductionQueue.UpgradeUnit,
seconds ? seconds + timestamp() : 0
);
}
}

View File

@ -11,6 +11,9 @@ export class GuildHallPageGrabber extends Grabber {
}
const seconds = grabRemainingSeconds();
this.storage.storeQueueTaskEnding(ProductionQueue.Celebration, seconds ? seconds + timestamp() : 0);
this.storage.storeQueueTaskEnding(
ProductionQueue.Celebration,
seconds ? seconds + timestamp() : 0
);
}
}

View File

@ -16,7 +16,9 @@ export class VillageOverviewPageGrabber extends Grabber {
this.storage.storeBuildingQueueInfo(this.grabBuildingQueueInfoOrDefault());
const buildingQueueInfo = this.grabBuildingQueueInfoOrDefault();
const buildingEndTime = buildingQueueInfo.seconds ? buildingQueueInfo.seconds + timestamp() : 0;
const buildingEndTime = buildingQueueInfo.seconds
? buildingQueueInfo.seconds + timestamp()
: 0;
this.storage.storeQueueTaskEnding(ProductionQueue.Building, buildingEndTime);
}

View File

@ -14,7 +14,9 @@ export function clickBuildButton(typeId: number) {
btn.trigger('click');
}
export function createBuildButton(onClickHandler: (buildTypeId: number, resources: Resources) => void) {
export function createBuildButton(
onClickHandler: (buildTypeId: number, resources: Resources) => void
) {
const $els = jQuery('[id^=contract_building]');
$els.each((idx, el) => {
const $el = jQuery(el);

View File

@ -28,7 +28,11 @@ export function clickCelebrationButton() {
$btn.trigger('click');
}
function createCelebrationButton($blockEl: JQuery, idx: number, onClickHandler: CelebrationClickHandler) {
function createCelebrationButton(
$blockEl: JQuery,
idx: number,
onClickHandler: CelebrationClickHandler
) {
const resources = grabResources($blockEl);
const id = uniqId();

View File

@ -24,7 +24,10 @@ export function createSendResourcesButton(onClickHandler: SendResourcesClickHand
getNumber(sendSelect.find('#r3').val()),
getNumber(sendSelect.find('#r4').val())
);
const crd = new Coordinates(getNumber(jQuery('#xCoordInput').val()), getNumber(jQuery('#yCoordInput').val()));
const crd = new Coordinates(
getNumber(jQuery('#xCoordInput').val()),
getNumber(jQuery('#yCoordInput').val())
);
onClickHandler(resources, crd);
};

View File

@ -17,7 +17,9 @@ export function createTrainTroopButtons(
return;
}
const id = uniqId();
$el.find('.details').append(`<div style="padding: 8px 0"><a id="${id}" href="#">Обучить</a></div>`);
$el.find('.details').append(
`<div style="padding: 8px 0"><a id="${id}" href="#">Обучить</a></div>`
);
const resElement = $el.find('.resourceWrapper .resource');
const resources = grabResourcesFromList(resElement);
jQuery(`#${id}`).on('click', evt => {

View File

@ -10,7 +10,12 @@ import { Resources } from '../Core/Resources';
import { Coordinates } from '../Core/Village';
import { SendResourcesTask } from '../Task/SendResourcesTask';
import { EMBASSY_ID, HORSE_STABLE_ID, PALACE_ID, QUARTERS_ID } from '../Core/Buildings';
import { BuildingPageAttributes, isForgePage, isGuildHallPage, isMarketSendResourcesPage } from './PageDetectors';
import {
BuildingPageAttributes,
isForgePage,
isGuildHallPage,
isMarketSendResourcesPage,
} from './PageDetectors';
import { createTrainTroopButtons } from './BuildingPage/TrooperPage';
import { createSendResourcesButton } from './BuildingPage/MarketPage';
import { createResearchButtons } from './BuildingPage/ForgePage';
@ -25,7 +30,11 @@ export class BuildingPageController {
private villageController: VillageController;
private readonly logger: Logger;
constructor(scheduler: Scheduler, attributes: BuildingPageAttributes, villageController: VillageController) {
constructor(
scheduler: Scheduler,
attributes: BuildingPageAttributes,
villageController: VillageController
) {
this.scheduler = scheduler;
this.attributes = attributes;
this.villageController = villageController;
@ -43,19 +52,27 @@ export class BuildingPageController {
}
if (buildTypeId === QUARTERS_ID) {
createTrainTroopButtons((troopId, res, count) => this.onScheduleTrainTroopers(troopId, res, count));
createTrainTroopButtons((troopId, res, count) =>
this.onScheduleTrainTroopers(troopId, res, count)
);
}
if (buildTypeId === HORSE_STABLE_ID) {
createTrainTroopButtons((troopId, res, count) => this.onScheduleTrainTroopers(troopId, res, count));
createTrainTroopButtons((troopId, res, count) =>
this.onScheduleTrainTroopers(troopId, res, count)
);
}
if (buildTypeId === EMBASSY_ID && sheetId === 1) {
createTrainTroopButtons((troopId, res, count) => this.onScheduleTrainTroopers(troopId, res, count));
createTrainTroopButtons((troopId, res, count) =>
this.onScheduleTrainTroopers(troopId, res, count)
);
}
if (buildTypeId === PALACE_ID && sheetId === 1) {
createTrainTroopButtons((troopId, res, count) => this.onScheduleTrainTroopers(troopId, res, count));
createTrainTroopButtons((troopId, res, count) =>
this.onScheduleTrainTroopers(troopId, res, count)
);
}
if (isMarketSendResourcesPage()) {

View File

@ -1,6 +1,13 @@
import { Logger } from '../Logger';
import { Args } from './Args';
import { ImmutableTaskList, Task, TaskId, TaskList, TaskProvider, uniqTaskId } from './TaskProvider';
import {
ImmutableTaskList,
Task,
TaskId,
TaskList,
TaskProvider,
uniqTaskId,
} from './TaskProvider';
export class TaskQueue {
private provider: TaskProvider;

View File

@ -22,7 +22,9 @@ export class ResourceTransferCalculator {
const recipientController = this.factory.createController(toVillageId);
const multiplier = senderState.settings.sendResourcesMultiplier;
const senderReadyResources = senderController.getAvailableForSendResources().downTo(multiplier);
const senderReadyResources = senderController
.getAvailableForSendResources()
.downTo(multiplier);
const recipientNeedResources = recipientController.getRequiredResources().upTo(multiplier);
const contractResources = senderReadyResources.min(recipientNeedResources);
@ -44,6 +46,11 @@ export class ResourceTransferCalculator {
{ name: 'Ready to transfer', ...readyToTransfer },
]);
return { fromVillageId, toVillageId, resources: readyToTransfer, score: readyToTransfer.amount() };
return {
fromVillageId,
toVillageId,
resources: readyToTransfer,
score: readyToTransfer.amount(),
};
}
}

View File

@ -1,6 +1,5 @@
import { around, timestamp } from './utils';
import { TaskQueue } from './Queue/TaskQueue';
import { SendOnAdventureTask } from './Task/SendOnAdventureTask';
import { BalanceHeroResourcesTask } from './Task/BalanceHeroResourcesTask';
import { Logger } from './Logger';
import { GrabVillageState } from './Task/GrabVillageState';
@ -9,12 +8,10 @@ import { UpdateResourceContracts } from './Task/UpdateResourceContracts';
import { SendResourcesTask } from './Task/SendResourcesTask';
import { Args } from './Queue/Args';
import { ImmutableTaskList, Task, TaskId, uniqTaskId, withTime } from './Queue/TaskProvider';
import { MARKET_ID } from './Core/Buildings';
import { VillageRepositoryInterface } from './VillageRepository';
import { isProductionTask } from './Core/ProductionQueue';
import { VillageFactory } from './VillageFactory';
import { RunVillageProductionTask } from './Task/RunVillageProductionTask';
import { VillageNotFound } from './Errors';
export interface NextExecution {
task?: Task;
@ -47,7 +44,9 @@ export class Scheduler {
const villages = this.villageRepository.all();
for (let village of villages) {
this.createUniqTaskTimer(5 * 60, RunVillageProductionTask.name, { villageId: village.id });
this.createUniqTaskTimer(5 * 60, RunVillageProductionTask.name, {
villageId: village.id,
});
}
this.createUniqTaskTimer(5 * 60, GrabVillageState.name);
@ -127,7 +126,9 @@ export class Scheduler {
scheduleUniqTask(name: string, args: Args, ts?: number | undefined): void {
let alreadyHasTask;
if (args.villageId) {
alreadyHasTask = this.taskQueue.has(t => t.name === name && t.args.villageId === args.villageId);
alreadyHasTask = this.taskQueue.has(
t => t.name === name && t.args.villageId === args.villageId
);
} else {
alreadyHasTask = this.taskQueue.has(t => t.name === name);
}

View File

@ -82,7 +82,9 @@ export class VillageStorage {
}
getIncomingMerchants(): ReadonlyArray<IncomingMerchant> {
const objects = this.storage.getTypedList<object>(INCOMING_MERCHANTS_KEY, { factory: () => ({}) });
const objects = this.storage.getTypedList<object>(INCOMING_MERCHANTS_KEY, {
factory: () => ({}),
});
return objects.map((plain: object) => {
const m = new IncomingMerchant(new Resources(0, 0, 0, 0), 0);
if (typeof plain !== 'object') {

View File

@ -19,7 +19,11 @@ export class BuildBuildingTask extends TaskController {
[
GoToPageAction.name,
{
path: path('/build.php', { newdid: args.villageId, id: args.buildId, category: args.categoryId }),
path: path('/build.php', {
newdid: args.villageId,
id: args.buildId,
category: args.categoryId,
}),
},
],
[BuildBuildingAction.name],

View File

@ -17,6 +17,9 @@ export class CelebrationTask extends TaskController {
id: args.buildId || undefined,
};
return [[GoToPageAction.name, { path: path('/build.php', pathArgs) }], [CelebrationAction.name]];
return [
[GoToPageAction.name, { path: path('/build.php', pathArgs) }],
[CelebrationAction.name],
];
}
}

View File

@ -17,6 +17,9 @@ export class ForgeImprovementTask extends TaskController {
id: args.buildId || undefined,
};
return [[GoToPageAction.name, { path: path('/build.php', pathArgs) }], [ForgeImprovementAction.name]];
return [
[GoToPageAction.name, { path: path('/build.php', pathArgs) }],
[ForgeImprovementAction.name],
];
}
}

View File

@ -15,7 +15,10 @@ export class UpdateResourceContracts extends TaskController {
.map(v => this.factory.createTaskCollection(v.id).getTasks())
.reduce((acc, tasks) => acc.concat(tasks), []);
const paths = uniqPaths([...this.walkUpgradeTasks(tasks), ...this.walkImprovementTask(tasks)]);
const paths = uniqPaths([
...this.walkUpgradeTasks(tasks),
...this.walkImprovementTask(tasks),
]);
return paths.map(p => [GoToPageAction.name, { path: path(p.name, p.query) }]);
}

View File

@ -23,7 +23,9 @@ export class TaskQueueRenderer {
'padding': '8px 6px',
});
tasks.forEach(task => {
ul.append(jQuery('<li></li>').text(formatDate(task.ts) + ' ' + task.name + ' ' + task.id));
ul.append(
jQuery('<li></li>').text(formatDate(task.ts) + ' ' + task.name + ' ' + task.id)
);
});
const el = jQuery(`#${ID}`);

View File

@ -61,6 +61,10 @@ export class VillageFactory {
createController(villageId: number): VillageController {
const village = this.villageRepository.get(villageId);
return new VillageController(village.id, this.createTaskCollection(village.id), this.createState(village.id));
return new VillageController(
village.id,
this.createTaskCollection(village.id),
this.createState(village.id)
);
}
}

View File

@ -90,7 +90,11 @@ export interface VillageState extends VillageOwnState {
commitments: Resources;
}
function calcResourceBalance(resources: Resources, current: Resources, performance: Resources): ResourceLineState {
function calcResourceBalance(
resources: Resources,
current: Resources,
performance: Resources
): ResourceLineState {
return {
resources,
balance: current.sub(resources),
@ -98,7 +102,11 @@ function calcResourceBalance(resources: Resources, current: Resources, performan
};
}
function calcStorageBalance(resources: Resources, storage: Resources, performance: Resources): VillageStorageState {
function calcStorageBalance(
resources: Resources,
storage: Resources,
performance: Resources
): VillageStorageState {
return {
resources,
capacity: storage,
@ -109,12 +117,20 @@ function calcStorageBalance(resources: Resources, storage: Resources, performanc
};
}
function timeToAllResources(current: Resources, desired: Resources, performance: Resources): GatheringTime {
function timeToAllResources(
current: Resources,
desired: Resources,
performance: Resources
): GatheringTime {
const timings = calcGatheringTimings(current, desired, performance);
return timings.slowest;
}
function timeToFastestResource(current: Resources, desired: Resources, performance: Resources): GatheringTime {
function timeToFastestResource(
current: Resources,
desired: Resources,
performance: Resources
): GatheringTime {
const timings = calcGatheringTimings(current, desired, performance);
return timings.fastest;
}
@ -124,7 +140,9 @@ function calcIncomingResources(storage: VillageStorage): Resources {
}
function taskResourceReducer(resources: Resources, task: Task) {
return task.args.resources ? resources.add(Resources.fromObject(task.args.resources)) : resources;
return task.args.resources
? resources.add(Resources.fromObject(task.args.resources))
: resources;
}
function createProductionQueueState(
@ -144,14 +162,20 @@ function createProductionQueueState(
queue,
isActive: tasks.length !== 0 || taskEndingTimestamp > timestamp(),
currentTaskFinishTimestamp: taskEndingTimestamp,
currentTaskFinishSeconds: Math.max(taskEndingTimestamp ? taskEndingTimestamp - timestamp() : 0, 0),
currentTaskFinishSeconds: Math.max(
taskEndingTimestamp ? taskEndingTimestamp - timestamp() : 0,
0
),
firstTask: calcResourceBalance(firstTaskResources, resources, performance),
allTasks: calcResourceBalance(allTaskResources, resources, performance),
taskCount: tasks.length,
};
}
function createAllProductionQueueStates(storage: VillageStorage, taskCollection: VillageTaskCollection) {
function createAllProductionQueueStates(
storage: VillageStorage,
taskCollection: VillageTaskCollection
) {
let result: { [queue: string]: VillageProductionQueueState } = {};
for (let queue of OrderedProductionQueues) {
result[queue] = createProductionQueueState(queue, storage, taskCollection);
@ -204,13 +228,18 @@ function createVillageOwnStates(
return result;
}
function createVillageState(state: VillageOwnState, ownStates: VillageOwnStateDictionary): VillageState {
function createVillageState(
state: VillageOwnState,
ownStates: VillageOwnStateDictionary
): VillageState {
const villageIds = Object.keys(ownStates).map(k => +k);
const commitments = villageIds.reduce((memo, shipmentVillageId) => {
const shipmentVillageState = ownStates[shipmentVillageId];
const shipmentVillageRequired = shipmentVillageState.required;
const shipmentVillageIncoming = shipmentVillageState.incomingResources;
const targetVillageMissing = shipmentVillageRequired.balance.add(shipmentVillageIncoming).min(Resources.zero());
const targetVillageMissing = shipmentVillageRequired.balance
.add(shipmentVillageIncoming)
.min(Resources.zero());
return memo.add(targetVillageMissing);
}, Resources.zero());
return { ...state, commitments };
@ -249,11 +278,19 @@ export class VillageStateFactory {
}
getAllVillageStates(): Array<VillageState> {
return getVillageStates(this.villageRepository.all(), this.storageFactory, this.taskCollectionFactory);
return getVillageStates(
this.villageRepository.all(),
this.storageFactory,
this.taskCollectionFactory
);
}
getVillageState(villageId: number): VillageState {
const states = getVillageStates(this.villageRepository.all(), this.storageFactory, this.taskCollectionFactory);
const states = getVillageStates(
this.villageRepository.all(),
this.storageFactory,
this.taskCollectionFactory
);
const needle = states.find(s => s.id === villageId);
if (!needle) {
throw new VillageNotFound(`Village ${villageId} not found`);

View File

@ -45,7 +45,9 @@ export class VillageTaskCollection {
throw new Error(`Task "${name}" is not production task`);
}
if (args.villageId !== this.villageId) {
throw new Error(`Task village id (${args.villageId}) not equal controller village id (${this.villageId}`);
throw new Error(
`Task village id (${args.villageId}) not equal controller village id (${this.villageId}`
);
}
const task = new Task(uniqTaskId(), 0, name, { villageId: this.villageId, ...args });
@ -86,7 +88,9 @@ export class VillageTaskCollection {
const maxCapacity = Resources.fromStorage(this.storage.getResourceStorage());
return firstReadyGroup.tasks.find(
t => !t.args.resources || maxCapacity.allGreaterOrEqual(Resources.fromObject(t.args.resources))
t =>
!t.args.resources ||
maxCapacity.allGreaterOrEqual(Resources.fromObject(t.args.resources))
);
}
@ -97,7 +101,8 @@ export class VillageTaskCollection {
updateResources(resources: Resources, attr: ContractAttributes): void {
if (attr.type === ContractType.UpgradeBuilding && attr.buildId) {
const predicate = (t: Task) => t.name === UpgradeBuildingTask.name && t.args.buildId === attr.buildId;
const predicate = (t: Task) =>
t.name === UpgradeBuildingTask.name && t.args.buildId === attr.buildId;
this.modifyTasks(predicate, withResources(resources));
}
if (attr.type === ContractType.ImproveTrooper && attr.buildId && attr.unitId) {

View File

@ -30,6 +30,8 @@ describe('Statistics', function() {
for (let i = 0; i < 120; ++i) {
statistics.incrementAction(baseTime + 3600 * i);
}
expect(Object.keys(statistics.getActionStatistics())).to.has.lengthOf(Statistics.keepRecords);
expect(Object.keys(statistics.getActionStatistics())).to.has.lengthOf(
Statistics.keepRecords
);
});
});

View File

@ -22,7 +22,10 @@ describe('Task Queue', function() {
});
it('Can remove task by id', function() {
const provider = new ArrayTaskProvider([new Task('id1', 1, 'task1', {}), new Task('id2', 2, 'task2', {})]);
const provider = new ArrayTaskProvider([
new Task('id1', 1, 'task1', {}),
new Task('id2', 2, 'task2', {}),
]);
const queue = new TaskQueue(provider, new NullLogger());
queue.remove(t => t.id === 'id1');
const tasks = provider.getTasks();