Auto build warehouse, granary and crop fields
This commit is contained in:
parent
7653c7b6e7
commit
effc1b1626
@ -4,6 +4,7 @@ import { BuildingPageController } from './Page/BuildingPageController';
|
|||||||
import { UpgradeBuildingTask } from './Task/UpgradeBuildingTask';
|
import { UpgradeBuildingTask } from './Task/UpgradeBuildingTask';
|
||||||
import { grabActiveVillageId } from './Page/VillageBlock';
|
import { grabActiveVillageId } from './Page/VillageBlock';
|
||||||
import {
|
import {
|
||||||
|
grabBuildingSlots,
|
||||||
grabResourceSlots,
|
grabResourceSlots,
|
||||||
onBuildingSlotCtrlClick,
|
onBuildingSlotCtrlClick,
|
||||||
onResourceSlotCtrlClick,
|
onResourceSlotCtrlClick,
|
||||||
@ -126,6 +127,7 @@ export class ControlPanel {
|
|||||||
.map(t => t.args.buildId || 0);
|
.map(t => t.args.buildId || 0);
|
||||||
|
|
||||||
if (p.pathname === '/dorf1.php') {
|
if (p.pathname === '/dorf1.php') {
|
||||||
|
console.log('RSLOTS', grabResourceSlots());
|
||||||
showResourceSlotIds(getBuildingsInQueue());
|
showResourceSlotIds(getBuildingsInQueue());
|
||||||
state.quickActions.push(...this.createDepositsQuickActions(villageId));
|
state.quickActions.push(...this.createDepositsQuickActions(villageId));
|
||||||
onResourceSlotCtrlClick(buildId => {
|
onResourceSlotCtrlClick(buildId => {
|
||||||
@ -135,6 +137,7 @@ export class ControlPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (p.pathname === '/dorf2.php') {
|
if (p.pathname === '/dorf2.php') {
|
||||||
|
console.log('BSLOTS', grabBuildingSlots());
|
||||||
showBuildingSlotIds(getBuildingsInQueue());
|
showBuildingSlotIds(getBuildingsInQueue());
|
||||||
onBuildingSlotCtrlClick(buildId => {
|
onBuildingSlotCtrlClick(buildId => {
|
||||||
this.onSlotCtrlClick(villageId, buildId);
|
this.onSlotCtrlClick(villageId, buildId);
|
||||||
|
@ -1,11 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<table class="task-list">
|
<table class="task-list">
|
||||||
<tr v-for="task in tasks">
|
<tr v-for="task in tasks">
|
||||||
<td
|
<td class="col-name" v-text="taskLabel(task)" :title="task.name + ', ' + task.id"></td>
|
||||||
class="col-name"
|
|
||||||
v-text="(task.canBeBuilt ? '' : '(!) ') + task.name"
|
|
||||||
:title="task.name + ', ' + task.id"
|
|
||||||
></td>
|
|
||||||
<td class="col-actions">
|
<td class="col-actions">
|
||||||
<a href="#" class="action" @click.prevent="upTask(task.id)" title="Поднять задачу">up</a>
|
<a href="#" class="action" @click.prevent="upTask(task.id)" title="Поднять задачу">up</a>
|
||||||
<a href="#" class="action" @click.prevent="downTask(task.id)" title="Опустить задачу">dn</a>
|
<a href="#" class="action" @click.prevent="downTask(task.id)" title="Опустить задачу">dn</a>
|
||||||
@ -30,6 +26,19 @@ export default {
|
|||||||
props: ['villageId', 'tasks'],
|
props: ['villageId', 'tasks'],
|
||||||
computed: {},
|
computed: {},
|
||||||
methods: {
|
methods: {
|
||||||
|
taskLabel(task) {
|
||||||
|
let taskStatus = '';
|
||||||
|
if (!task.isEnoughWarehouseCapacity) {
|
||||||
|
taskStatus += 'w!';
|
||||||
|
}
|
||||||
|
if (!task.isEnoughGranaryCapacity) {
|
||||||
|
taskStatus += 'g!';
|
||||||
|
}
|
||||||
|
if (taskStatus) {
|
||||||
|
taskStatus = '(' + taskStatus + ') ';
|
||||||
|
}
|
||||||
|
return taskStatus + task.name;
|
||||||
|
},
|
||||||
upTask(taskId) {
|
upTask(taskId) {
|
||||||
this.$store.dispatch(Actions.UpVillageTask, { villageId: this.villageId, taskId });
|
this.$store.dispatch(Actions.UpVillageTask, { villageId: this.villageId, taskId });
|
||||||
},
|
},
|
||||||
|
22
src/Game.ts
22
src/Game.ts
@ -7,18 +7,34 @@ export class BuildingQueueInfo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ResourceSlot {
|
export interface Slot {
|
||||||
readonly buildId: number;
|
readonly buildId: number;
|
||||||
readonly type: ResourceType;
|
|
||||||
readonly level: number;
|
readonly level: number;
|
||||||
readonly isReady: boolean;
|
readonly isReady: boolean;
|
||||||
readonly isUnderConstruction: boolean;
|
readonly isUnderConstruction: boolean;
|
||||||
readonly isMaxLevel: boolean;
|
readonly isMaxLevel: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ResourceSlot extends Slot {
|
||||||
|
readonly type: ResourceType;
|
||||||
|
}
|
||||||
|
|
||||||
export const ResourceSlotDefaults: ResourceSlot = {
|
export const ResourceSlotDefaults: ResourceSlot = {
|
||||||
buildId: 0,
|
|
||||||
type: ResourceType.Lumber,
|
type: ResourceType.Lumber,
|
||||||
|
buildId: 0,
|
||||||
|
level: 0,
|
||||||
|
isReady: false,
|
||||||
|
isUnderConstruction: false,
|
||||||
|
isMaxLevel: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface BuildingSlot extends Slot {
|
||||||
|
readonly buildTypeId: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const BuildingSlotDefaults: BuildingSlot = {
|
||||||
|
buildTypeId: 0,
|
||||||
|
buildId: 0,
|
||||||
level: 0,
|
level: 0,
|
||||||
isReady: false,
|
isReady: false,
|
||||||
isUnderConstruction: false,
|
isUnderConstruction: false,
|
||||||
|
@ -7,6 +7,7 @@ import { BuildingContractGrabber } from './BuildingContractGrabber';
|
|||||||
import { ForgePageGrabber } from './ForgePageGrabber';
|
import { ForgePageGrabber } from './ForgePageGrabber';
|
||||||
import { GuildHallPageGrabber } from './GuildHallPageGrabber';
|
import { GuildHallPageGrabber } from './GuildHallPageGrabber';
|
||||||
import { VillageFactory } from '../VillageFactory';
|
import { VillageFactory } from '../VillageFactory';
|
||||||
|
import { VillageBuildingsPageGrabber } from './VillageBuildingsPageGrabber';
|
||||||
|
|
||||||
export class GrabberManager {
|
export class GrabberManager {
|
||||||
private factory: VillageFactory;
|
private factory: VillageFactory;
|
||||||
@ -28,6 +29,7 @@ export class GrabberManager {
|
|||||||
const grabbers: Array<Grabber> = [];
|
const grabbers: Array<Grabber> = [];
|
||||||
grabbers.push(new VillageResourceGrabber(taskCollection, storage));
|
grabbers.push(new VillageResourceGrabber(taskCollection, storage));
|
||||||
grabbers.push(new VillageOverviewPageGrabber(taskCollection, storage));
|
grabbers.push(new VillageOverviewPageGrabber(taskCollection, storage));
|
||||||
|
grabbers.push(new VillageBuildingsPageGrabber(taskCollection, storage));
|
||||||
grabbers.push(new HeroPageGrabber(taskCollection, storage));
|
grabbers.push(new HeroPageGrabber(taskCollection, storage));
|
||||||
grabbers.push(new MarketPageGrabber(taskCollection, storage));
|
grabbers.push(new MarketPageGrabber(taskCollection, storage));
|
||||||
grabbers.push(new BuildingContractGrabber(taskCollection, storage));
|
grabbers.push(new BuildingContractGrabber(taskCollection, storage));
|
||||||
|
14
src/Grabber/VillageBuildingsPageGrabber.ts
Normal file
14
src/Grabber/VillageBuildingsPageGrabber.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { Grabber } from './Grabber';
|
||||||
|
import { parseLocation } from '../utils';
|
||||||
|
import { grabBuildingSlots } from '../Page/SlotBlock';
|
||||||
|
|
||||||
|
export class VillageBuildingsPageGrabber extends Grabber {
|
||||||
|
grab(): void {
|
||||||
|
const p = parseLocation();
|
||||||
|
if (p.pathname !== '/dorf2.php') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.storage.storeBuildingSlots(grabBuildingSlots());
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
import { elClassId, getNumber } from '../utils';
|
import { elClassId, getNumber } from '../utils';
|
||||||
import { ResourceSlot } from '../Game';
|
import { BuildingSlot, ResourceSlot } from '../Game';
|
||||||
import { numberToResourceType } from '../Core/ResourceType';
|
import { numberToResourceType } from '../Core/ResourceType';
|
||||||
|
|
||||||
interface SlotElement {
|
interface SlotElement {
|
||||||
@ -90,3 +90,22 @@ function makeResourceSlot(slot: SlotElement): ResourceSlot {
|
|||||||
export function grabResourceSlots(): Array<ResourceSlot> {
|
export function grabResourceSlots(): Array<ResourceSlot> {
|
||||||
return slotElements('buildingSlot').map(makeResourceSlot);
|
return slotElements('buildingSlot').map(makeResourceSlot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function makeBuildingSlot(slot: SlotElement): BuildingSlot {
|
||||||
|
const $el = jQuery(slot.el);
|
||||||
|
const classes = $el.attr('class');
|
||||||
|
const $parent = $el.closest('.buildingSlot');
|
||||||
|
const parentClasses = $parent.attr('class');
|
||||||
|
return {
|
||||||
|
buildId: getNumber(elClassId(classes, 'aid')),
|
||||||
|
buildTypeId: getNumber(elClassId(parentClasses, 'g')),
|
||||||
|
level: getNumber(elClassId(classes, 'level')),
|
||||||
|
isReady: !$el.hasClass('notNow'),
|
||||||
|
isUnderConstruction: $el.hasClass('underConstruction'),
|
||||||
|
isMaxLevel: $el.hasClass('maxLevel'),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function grabBuildingSlots(): Array<BuildingSlot> {
|
||||||
|
return slotElements('aid').map(makeBuildingSlot);
|
||||||
|
}
|
||||||
|
@ -20,7 +20,12 @@ export function uniqTaskId(): TaskId {
|
|||||||
return 'tid.' + ts + '.' + String(idSequence).padStart(4, '0') + '.' + uniqId('');
|
return 'tid.' + ts + '.' + String(idSequence).padStart(4, '0') + '.' + uniqId('');
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Task {
|
export interface TaskCore {
|
||||||
|
readonly name: string;
|
||||||
|
readonly args: Args;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Task implements TaskCore {
|
||||||
readonly id: TaskId;
|
readonly id: TaskId;
|
||||||
readonly ts: number;
|
readonly ts: number;
|
||||||
readonly name: string;
|
readonly name: string;
|
||||||
@ -51,7 +56,26 @@ export interface TaskTransformer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function isInQueue(queue: ProductionQueue): TaskMatcher {
|
export function isInQueue(queue: ProductionQueue): TaskMatcher {
|
||||||
return (task: Task) => getProductionQueue(task.name) === queue;
|
return (task: TaskCore) => getProductionQueue(task.name) === queue;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isBuildingPlanned(
|
||||||
|
name: string,
|
||||||
|
buildId: number | undefined,
|
||||||
|
buildTypeId: number | undefined
|
||||||
|
) {
|
||||||
|
return (task: TaskCore) => {
|
||||||
|
if (name !== task.name) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (buildId && task.args.buildId) {
|
||||||
|
return buildId === task.args.buildId;
|
||||||
|
}
|
||||||
|
if (buildTypeId && task.args.buildTypeId) {
|
||||||
|
return buildTypeId === task.args.buildTypeId;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function withTime(ts: number): TaskTransformer {
|
export function withTime(ts: number): TaskTransformer {
|
||||||
|
@ -6,7 +6,7 @@ import { VillageSettings, VillageSettingsDefaults } from '../Core/Village';
|
|||||||
import { ProductionQueue } from '../Core/ProductionQueue';
|
import { ProductionQueue } from '../Core/ProductionQueue';
|
||||||
import { getNumber } from '../utils';
|
import { getNumber } from '../utils';
|
||||||
import { Task, uniqTaskId } from '../Queue/TaskProvider';
|
import { Task, uniqTaskId } from '../Queue/TaskProvider';
|
||||||
import { ResourceSlot, ResourceSlotDefaults } from '../Game';
|
import { BuildingSlot, BuildingSlotDefaults, ResourceSlot, ResourceSlotDefaults } from '../Game';
|
||||||
|
|
||||||
const RESOURCES_KEY = 'resources';
|
const RESOURCES_KEY = 'resources';
|
||||||
const CAPACITY_KEY = 'capacity';
|
const CAPACITY_KEY = 'capacity';
|
||||||
@ -96,6 +96,16 @@ export class VillageStorage {
|
|||||||
this.storage.set(RESOURCE_SLOTS_KEY, slots);
|
this.storage.set(RESOURCE_SLOTS_KEY, slots);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getBuildingSlots(): ReadonlyArray<BuildingSlot> {
|
||||||
|
return this.storage.getTypedList<BuildingSlot>(BUILDING_SLOTS_KEY, {
|
||||||
|
factory: () => Object.assign({}, BuildingSlotDefaults),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
storeBuildingSlots(slots: ReadonlyArray<BuildingSlot>): void {
|
||||||
|
this.storage.set(BUILDING_SLOTS_KEY, slots);
|
||||||
|
}
|
||||||
|
|
||||||
getSettings(): VillageSettings {
|
getSettings(): VillageSettings {
|
||||||
return this.storage.getTyped<VillageSettings>(SETTINGS_KEY, {
|
return this.storage.getTyped<VillageSettings>(SETTINGS_KEY, {
|
||||||
factory: () => Object.assign({}, VillageSettingsDefaults),
|
factory: () => Object.assign({}, VillageSettingsDefaults),
|
||||||
|
@ -13,6 +13,15 @@ export function goToResourceViewPage(villageId: number): ActionDefinition {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function goToBuildingsViewPage(villageId: number): ActionDefinition {
|
||||||
|
return {
|
||||||
|
name: GoToPageAction.name,
|
||||||
|
args: {
|
||||||
|
path: path('/dorf2.php', { newdid: villageId }),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function goToMarketSendResourcesPage(villageId: number): ActionDefinition {
|
export function goToMarketSendResourcesPage(villageId: number): ActionDefinition {
|
||||||
return {
|
return {
|
||||||
name: GoToPageAction.name,
|
name: GoToPageAction.name,
|
||||||
@ -44,6 +53,7 @@ export function scanAllVillagesBundle(villages: Array<Village>): Array<ActionDef
|
|||||||
const actions: Array<ActionDefinition> = [];
|
const actions: Array<ActionDefinition> = [];
|
||||||
for (let village of villages) {
|
for (let village of villages) {
|
||||||
actions.push(goToResourceViewPage(village.id));
|
actions.push(goToResourceViewPage(village.id));
|
||||||
|
actions.push(goToBuildingsViewPage(village.id));
|
||||||
actions.push(goToMarketSendResourcesPage(village.id));
|
actions.push(goToMarketSendResourcesPage(village.id));
|
||||||
actions.push(goToForgePage(village.id));
|
actions.push(goToForgePage(village.id));
|
||||||
actions.push(goToGuildHallPage(village.id));
|
actions.push(goToGuildHallPage(village.id));
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { VillageTaskCollection } from './VillageTaskCollection';
|
import { VillageTaskCollection } from './VillageTaskCollection';
|
||||||
import { TaskId } from './Queue/TaskProvider';
|
import { isBuildingPlanned, TaskId } from './Queue/TaskProvider';
|
||||||
import { Args } from './Queue/Args';
|
import { Args } from './Queue/Args';
|
||||||
import { TaskState, VillageState } from './VillageState';
|
import { TaskState, VillageState } from './VillageState';
|
||||||
import { Resources } from './Core/Resources';
|
import { Resources } from './Core/Resources';
|
||||||
@ -9,6 +9,7 @@ import { ReceiveResourcesMode } from './Core/Village';
|
|||||||
import { ResourceType } from './Core/ResourceType';
|
import { ResourceType } from './Core/ResourceType';
|
||||||
import { UpgradeBuildingTask } from './Task/UpgradeBuildingTask';
|
import { UpgradeBuildingTask } from './Task/UpgradeBuildingTask';
|
||||||
import * as _ from 'underscore';
|
import * as _ from 'underscore';
|
||||||
|
import { GARNER_ID, WAREHOUSE_ID } from './Core/Buildings';
|
||||||
|
|
||||||
export class VillageController {
|
export class VillageController {
|
||||||
private readonly villageId: number;
|
private readonly villageId: number;
|
||||||
@ -152,39 +153,49 @@ export class VillageController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
planTasks(): void {
|
planTasks(): void {
|
||||||
const performance = this.state.performance;
|
if (this.state.tasks.length >= 100) {
|
||||||
|
return;
|
||||||
if (performance.crop < 100) {
|
|
||||||
this.planCropBuilding();
|
|
||||||
}
|
}
|
||||||
|
this.planCropBuilding();
|
||||||
|
this.planWarehouseBuilding();
|
||||||
|
this.planGranaryBuilding();
|
||||||
}
|
}
|
||||||
|
|
||||||
private planCropBuilding() {
|
private planCropBuilding() {
|
||||||
|
const performance = this.state.performance;
|
||||||
|
if (performance.crop >= 100) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const resourceSlots = this.storage.getResourceSlots();
|
const resourceSlots = this.storage.getResourceSlots();
|
||||||
const tasks = this.taskCollection.getTasks();
|
const tasks = this.taskCollection.getTasks();
|
||||||
|
|
||||||
const cropSlots = resourceSlots.filter(s => s.type === ResourceType.Crop);
|
const cropSlots = resourceSlots.filter(s => s.type === ResourceType.Crop && !s.isMaxLevel);
|
||||||
|
if (cropSlots.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Check, if crop field is building now
|
// Check, if crop field is building now
|
||||||
const isCropBuilding = cropSlots.filter(s => s.isUnderConstruction);
|
const underContraction = cropSlots.find(s => s.isUnderConstruction);
|
||||||
if (isCropBuilding) {
|
if (underContraction !== undefined) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check, if we already have crop task in queue
|
// Check, if we already have crop task in queue
|
||||||
const cropBuildIds = cropSlots.map(s => s.buildId);
|
const cropBuildIds = cropSlots.map(s => s.buildId);
|
||||||
const cropBuildingTaskInQueue = tasks.find(
|
for (let buildId of cropBuildIds) {
|
||||||
t => t.args.buildId && cropBuildIds.includes(t.args.buildId)
|
const upgradeTask = tasks.find(
|
||||||
);
|
isBuildingPlanned(UpgradeBuildingTask.name, buildId, undefined)
|
||||||
if (cropBuildingTaskInQueue !== undefined) {
|
);
|
||||||
return;
|
if (upgradeTask !== undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find ready for building slots and sort them by level
|
// Find ready for building slots and sort them by level
|
||||||
const readyCropSlots = cropSlots.filter(s => !s.isMaxLevel);
|
cropSlots.sort((s1, s2) => s1.level - s2.level);
|
||||||
readyCropSlots.sort((s1, s2) => s1.level - s2.level);
|
|
||||||
|
|
||||||
const targetCropBuildId = _.first(readyCropSlots)?.buildId;
|
const targetCropBuildId = _.first(cropSlots)?.buildId;
|
||||||
if (!targetCropBuildId) {
|
if (!targetCropBuildId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -193,4 +204,55 @@ export class VillageController {
|
|||||||
buildId: targetCropBuildId,
|
buildId: targetCropBuildId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private planWarehouseBuilding(): void {
|
||||||
|
this.planStorageBuilding(WAREHOUSE_ID, t => !t.isEnoughWarehouseCapacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
private planGranaryBuilding(): void {
|
||||||
|
this.planStorageBuilding(GARNER_ID, t => !t.isEnoughGranaryCapacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
private planStorageBuilding(
|
||||||
|
buildTypeId: number,
|
||||||
|
checkNeedEnlargeFunc: (task: TaskState) => boolean
|
||||||
|
): void {
|
||||||
|
const buildingSlots = this.storage.getBuildingSlots();
|
||||||
|
|
||||||
|
const storageSlots = buildingSlots.filter(
|
||||||
|
s => s.buildTypeId === buildTypeId && !s.isMaxLevel
|
||||||
|
);
|
||||||
|
if (storageSlots.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check, if storage is building now
|
||||||
|
const underConstruction = storageSlots.find(s => s.isUnderConstruction);
|
||||||
|
if (underConstruction !== undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const tasks = this.state.tasks;
|
||||||
|
|
||||||
|
// Check, if we have storage is in building queue
|
||||||
|
const storageBuildIds = storageSlots.map(s => s.buildId);
|
||||||
|
for (let buildId of storageBuildIds) {
|
||||||
|
const upgradeTask = tasks.find(
|
||||||
|
isBuildingPlanned(UpgradeBuildingTask.name, buildId, buildTypeId)
|
||||||
|
);
|
||||||
|
if (upgradeTask !== undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const needStorageEnlargeTasks = tasks.filter(checkNeedEnlargeFunc);
|
||||||
|
if (needStorageEnlargeTasks.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const firstSlot = _.first(storageSlots);
|
||||||
|
if (firstSlot) {
|
||||||
|
this.addTask(UpgradeBuildingTask.name, { buildId: firstSlot.buildId, buildTypeId });
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,8 @@ export interface TaskState {
|
|||||||
id: TaskId;
|
id: TaskId;
|
||||||
name: string;
|
name: string;
|
||||||
args: Args;
|
args: Args;
|
||||||
|
isEnoughWarehouseCapacity: boolean;
|
||||||
|
isEnoughGranaryCapacity: boolean;
|
||||||
canBeBuilt: boolean;
|
canBeBuilt: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,11 +224,29 @@ function getTaskResources(task: Task | TaskState | undefined): Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function makeTaskState(task: Task, maxResourcesForTask: Resources): TaskState {
|
function makeTaskState(task: Task, maxResourcesForTask: Resources): TaskState {
|
||||||
|
const taskResources = getTaskResources(task);
|
||||||
|
const taskWarehouseRequirements = new Resources(
|
||||||
|
taskResources.lumber,
|
||||||
|
taskResources.clay,
|
||||||
|
taskResources.iron,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
const isEnoughWarehouseCapacity = maxResourcesForTask.allGreaterOrEqual(
|
||||||
|
taskWarehouseRequirements
|
||||||
|
);
|
||||||
|
|
||||||
|
const taskGranaryRequirements = new Resources(0, 0, 0, taskResources.crop);
|
||||||
|
const isEnoughGranaryCapacity = maxResourcesForTask.allGreaterOrEqual(taskGranaryRequirements);
|
||||||
|
|
||||||
|
const canBeBuilt = isEnoughWarehouseCapacity && isEnoughGranaryCapacity;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: task.id,
|
id: task.id,
|
||||||
args: task.args,
|
args: task.args,
|
||||||
name: task.name,
|
name: task.name,
|
||||||
canBeBuilt: maxResourcesForTask.allGreaterOrEqual(getTaskResources(task)),
|
isEnoughWarehouseCapacity,
|
||||||
|
isEnoughGranaryCapacity,
|
||||||
|
canBeBuilt,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,13 +56,7 @@ export class VillageTaskCollection {
|
|||||||
throw new Error(`Task "${name}" is not production task`);
|
throw new Error(`Task "${name}" is not production task`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.villageId !== this.villageId) {
|
return new Task(uniqTaskId(), 0, name, { ...args, villageId: this.villageId });
|
||||||
throw new Error(
|
|
||||||
`Task village id (${args.villageId}) not equal controller village id (${this.villageId}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Task(uniqTaskId(), 0, name, { villageId: this.villageId, ...args });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
removeTask(taskId: TaskId) {
|
removeTask(taskId: TaskId) {
|
||||||
|
@ -59,8 +59,9 @@ export function elClassId(classes: string | undefined, prefix: string): number |
|
|||||||
}
|
}
|
||||||
let result: number | undefined = undefined;
|
let result: number | undefined = undefined;
|
||||||
classes.split(/\s/).forEach(part => {
|
classes.split(/\s/).forEach(part => {
|
||||||
if (part.startsWith(prefix)) {
|
const match = part.match(new RegExp(prefix + '(\\d+)'));
|
||||||
result = toNumber(part.substr(prefix.length));
|
if (match) {
|
||||||
|
result = toNumber(match[1]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
|
@ -1,25 +1,39 @@
|
|||||||
import { it, describe } from 'mocha';
|
import { it, describe } from 'mocha';
|
||||||
import { expect } from 'chai';
|
import { expect } from 'chai';
|
||||||
import { getNumber } from '../src/utils';
|
import { elClassId, getNumber } from '../src/utils';
|
||||||
|
|
||||||
describe('Utils', function() {
|
describe('Utils', function() {
|
||||||
it('Can parse positive number', function() {
|
describe('getNumber', function() {
|
||||||
const text = '123';
|
it('Can parse positive number', function() {
|
||||||
expect(getNumber(text)).to.be.equals(123);
|
const text = '123';
|
||||||
|
expect(getNumber(text)).to.be.equals(123);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Can parse positive number with noise', function() {
|
||||||
|
const text = ' 123 ';
|
||||||
|
expect(getNumber(text)).to.be.equals(123);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Can parse negative number', function() {
|
||||||
|
const text = '-146';
|
||||||
|
expect(getNumber(text)).to.be.equals(-146);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Can parse negative number with minus sign', function() {
|
||||||
|
const text = '\u2212132';
|
||||||
|
expect(getNumber(text)).to.be.equals(-132);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Can parse positive number with noise', function() {
|
describe('elClassId', function() {
|
||||||
const text = ' 123 ';
|
it('Can parse number with prefix', function() {
|
||||||
expect(getNumber(text)).to.be.equals(123);
|
const text = 'foo bar12 baz';
|
||||||
});
|
expect(elClassId(text, 'bar')).to.be.equals(12);
|
||||||
|
});
|
||||||
|
|
||||||
it('Can parse negative number', function() {
|
it('Can parse number from parts with same prefix', function() {
|
||||||
const text = '-146';
|
const text = 'foo12 foobar';
|
||||||
expect(getNumber(text)).to.be.equals(-146);
|
expect(elClassId(text, 'foo')).to.be.equals(12);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Can parse negative number with minus sign', function() {
|
|
||||||
const text = '\u2212132';
|
|
||||||
expect(getNumber(text)).to.be.equals(-132);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user