Rebuild village state calculation
This commit is contained in:
parent
3d54294043
commit
129f107881
@ -1,4 +1,4 @@
|
|||||||
import { parseLocation, timestamp, uniqId, waitForLoad } from './utils';
|
import { notify, parseLocation, timestamp, uniqId, waitForLoad } from './utils';
|
||||||
import { Scheduler } from './Scheduler';
|
import { Scheduler } from './Scheduler';
|
||||||
import { BuildingPageController } from './Page/BuildingPageController';
|
import { BuildingPageController } from './Page/BuildingPageController';
|
||||||
import { UpgradeBuildingTask } from './Task/UpgradeBuildingTask';
|
import { UpgradeBuildingTask } from './Task/UpgradeBuildingTask';
|
||||||
@ -13,21 +13,35 @@ import Vue from 'vue';
|
|||||||
import DashboardApp from './DashboardView/Dashboard.vue';
|
import DashboardApp from './DashboardView/Dashboard.vue';
|
||||||
import { ResourcesToLevel } from './Task/ResourcesToLevel';
|
import { ResourcesToLevel } from './Task/ResourcesToLevel';
|
||||||
import { ConsoleLogger, Logger } from './Logger';
|
import { ConsoleLogger, Logger } from './Logger';
|
||||||
import { VillageStorage } from './Storage/VillageStorage';
|
|
||||||
import { Resources } from './Core/Resources';
|
|
||||||
import { Coordinates, Village } from './Core/Village';
|
|
||||||
import { calcGatheringTimings } from './Core/GatheringTimings';
|
|
||||||
import { DataStorage } from './DataStorage';
|
import { DataStorage } from './DataStorage';
|
||||||
import { getBuildingPageAttributes, isBuildingPage } from './Page/PageDetectors';
|
import { getBuildingPageAttributes, isBuildingPage } from './Page/PageDetectors';
|
||||||
import { debounce } from 'debounce';
|
import { debounce } from 'debounce';
|
||||||
import { ExecutionStorage } from './Storage/ExecutionStorage';
|
import { ExecutionStorage } from './Storage/ExecutionStorage';
|
||||||
import { ResourceStorage } from './Core/ResourceStorage';
|
import { createVillageStates, VillageState } from './VillageState';
|
||||||
|
import { Task } from './Queue/TaskProvider';
|
||||||
|
import { Action } from './Queue/ActionQueue';
|
||||||
|
|
||||||
interface QuickAction {
|
interface QuickAction {
|
||||||
label: string;
|
label: string;
|
||||||
cb: () => void;
|
cb: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface GameState {
|
||||||
|
name: string;
|
||||||
|
version: string;
|
||||||
|
activeVillageState: VillageState | undefined;
|
||||||
|
villageStates: ReadonlyArray<VillageState>;
|
||||||
|
taskList: ReadonlyArray<Task>;
|
||||||
|
actionList: ReadonlyArray<Action>;
|
||||||
|
quickActions: Array<QuickAction>;
|
||||||
|
pauseSeconds: number;
|
||||||
|
|
||||||
|
refresh(): void;
|
||||||
|
removeTask(taskId: string): void;
|
||||||
|
refreshVillages(): void;
|
||||||
|
pause(): void;
|
||||||
|
}
|
||||||
|
|
||||||
export class ControlPanel {
|
export class ControlPanel {
|
||||||
private readonly version: string;
|
private readonly version: string;
|
||||||
private readonly scheduler: Scheduler;
|
private readonly scheduler: Scheduler;
|
||||||
@ -48,18 +62,17 @@ export class ControlPanel {
|
|||||||
const villageId = grabActiveVillageId();
|
const villageId = grabActiveVillageId();
|
||||||
|
|
||||||
const scheduler = this.scheduler;
|
const scheduler = this.scheduler;
|
||||||
const quickActions: QuickAction[] = [];
|
|
||||||
|
|
||||||
const executionState = new ExecutionStorage();
|
const executionState = new ExecutionStorage();
|
||||||
|
|
||||||
const state: any = {
|
const state: GameState = {
|
||||||
name: 'Dashboard',
|
name: 'Control',
|
||||||
version: this.version,
|
version: this.version,
|
||||||
activeVillage: {},
|
activeVillageState: undefined,
|
||||||
villages: [],
|
villageStates: [],
|
||||||
taskList: [],
|
taskList: [],
|
||||||
actionList: [],
|
actionList: [],
|
||||||
quickActions: quickActions,
|
quickActions: [],
|
||||||
pauseSeconds: 0,
|
pauseSeconds: 0,
|
||||||
|
|
||||||
refresh() {
|
refresh() {
|
||||||
@ -76,12 +89,10 @@ export class ControlPanel {
|
|||||||
},
|
},
|
||||||
|
|
||||||
refreshVillages() {
|
refreshVillages() {
|
||||||
this.villages = grabVillageList().map(village => {
|
this.villageStates = createVillageStates(grabVillageList(), scheduler);
|
||||||
return new VillageController(village, new VillageStorage(village.id), scheduler);
|
for (let state of this.villageStates) {
|
||||||
});
|
if (state.village.active) {
|
||||||
for (let village of this.villages) {
|
this.activeVillageState = state;
|
||||||
if (village.active) {
|
|
||||||
this.activeVillage = village;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -111,7 +122,7 @@ export class ControlPanel {
|
|||||||
if (p.pathname === '/dorf1.php') {
|
if (p.pathname === '/dorf1.php') {
|
||||||
showResourceSlotIds(buildingsInQueue);
|
showResourceSlotIds(buildingsInQueue);
|
||||||
onResourceSlotCtrlClick(buildId => this.onResourceSlotCtrlClick(villageId, buildId));
|
onResourceSlotCtrlClick(buildId => this.onResourceSlotCtrlClick(villageId, buildId));
|
||||||
quickActions.push(...this.createDepositsQuickActions(villageId));
|
state.quickActions.push(...this.createDepositsQuickActions(villageId));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p.pathname === '/dorf2.php') {
|
if (p.pathname === '/dorf2.php') {
|
||||||
@ -126,12 +137,12 @@ export class ControlPanel {
|
|||||||
this.createControlPanel(state);
|
this.createControlPanel(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
private createControlPanel(state: any) {
|
private createControlPanel(gameState: GameState) {
|
||||||
const appId = `app-${uniqId()}`;
|
const appId = `app-${uniqId()}`;
|
||||||
jQuery('body').prepend(`<div id="${appId}"></div>`);
|
jQuery('body').prepend(`<div id="${appId}"></div>`);
|
||||||
new Vue({
|
new Vue({
|
||||||
el: `#${appId}`,
|
el: `#${appId}`,
|
||||||
data: state,
|
data: gameState,
|
||||||
render: h => h(DashboardApp),
|
render: h => h(DashboardApp),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -157,78 +168,6 @@ export class ControlPanel {
|
|||||||
|
|
||||||
private onResourceSlotCtrlClick(villageId: number, buildId: number) {
|
private onResourceSlotCtrlClick(villageId: number, buildId: number) {
|
||||||
this.scheduler.scheduleTask(UpgradeBuildingTask.name, { villageId, buildId });
|
this.scheduler.scheduleTask(UpgradeBuildingTask.name, { villageId, buildId });
|
||||||
const n = new Notification(`Building ${buildId} scheduled`);
|
notify(`Building ${buildId} scheduled`);
|
||||||
setTimeout(() => n && n.close(), 4000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class VillageController {
|
|
||||||
public readonly id: number;
|
|
||||||
public readonly name: string;
|
|
||||||
public readonly crd: Coordinates;
|
|
||||||
public readonly active: boolean;
|
|
||||||
public readonly lumber: number;
|
|
||||||
public readonly clay: number;
|
|
||||||
public readonly iron: number;
|
|
||||||
public readonly crop: number;
|
|
||||||
public readonly resources: Resources;
|
|
||||||
public readonly performance: Resources;
|
|
||||||
public readonly requiredResources: Resources;
|
|
||||||
public readonly requiredBalance: Resources;
|
|
||||||
public readonly totalRequiredResources: Resources;
|
|
||||||
public readonly totalRequiredBalance: Resources;
|
|
||||||
public readonly incomingResources: Resources;
|
|
||||||
public readonly storage: ResourceStorage;
|
|
||||||
public readonly warehouse: number;
|
|
||||||
public readonly granary: number;
|
|
||||||
public readonly buildRemainingSeconds: number;
|
|
||||||
|
|
||||||
constructor(village: Village, state: VillageStorage, scheduler: Scheduler) {
|
|
||||||
const resources = state.getResources();
|
|
||||||
const storage = state.getResourceStorage();
|
|
||||||
const performance = state.getResourcesPerformance();
|
|
||||||
const buildQueueInfo = state.getBuildingQueueInfo();
|
|
||||||
const requiredResources = scheduler.getVillageRequiredResources(village.id);
|
|
||||||
const totalRequiredResources = scheduler.getTotalVillageRequiredResources(village.id);
|
|
||||||
this.id = village.id;
|
|
||||||
this.name = village.name;
|
|
||||||
this.crd = village.crd;
|
|
||||||
this.active = village.active;
|
|
||||||
this.lumber = resources.lumber;
|
|
||||||
this.clay = resources.clay;
|
|
||||||
this.iron = resources.iron;
|
|
||||||
this.crop = resources.crop;
|
|
||||||
this.resources = resources;
|
|
||||||
this.performance = performance;
|
|
||||||
this.requiredResources = requiredResources;
|
|
||||||
this.requiredBalance = resources.sub(requiredResources);
|
|
||||||
this.totalRequiredResources = totalRequiredResources;
|
|
||||||
this.totalRequiredBalance = resources.sub(totalRequiredResources);
|
|
||||||
this.storage = storage;
|
|
||||||
this.warehouse = storage.warehouse;
|
|
||||||
this.granary = storage.granary;
|
|
||||||
this.buildRemainingSeconds = buildQueueInfo.seconds;
|
|
||||||
this.incomingResources = this.calcIncomingResources(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
timeToRequired() {
|
|
||||||
return this.timeToResources(this.requiredResources);
|
|
||||||
}
|
|
||||||
|
|
||||||
timeToTotalRequired() {
|
|
||||||
return this.timeToResources(this.totalRequiredResources);
|
|
||||||
}
|
|
||||||
|
|
||||||
private timeToResources(resources: Resources): number {
|
|
||||||
const timings = calcGatheringTimings(this.resources, resources, this.performance);
|
|
||||||
if (timings.never) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return timings.hours * 3600;
|
|
||||||
}
|
|
||||||
|
|
||||||
private calcIncomingResources(state: VillageStorage): Resources {
|
|
||||||
return state.getIncomingMerchants().reduce((m, i) => m.add(i.resources), new Resources(0, 0, 0, 0));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,8 +19,8 @@ export default {
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
villageName() {
|
villageName() {
|
||||||
let village = this.shared.activeVillage;
|
let state = this.shared.activeVillageState;
|
||||||
return village ? village.name : 'Unknown';
|
return state ? state.village.name : 'Unknown';
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -25,13 +25,12 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import * as dateFormat from 'dateformat';
|
import * as dateFormat from 'dateformat';
|
||||||
import { timestamp } from '../utils';
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
shared: this.$root.$data,
|
shared: this.$root.$data,
|
||||||
activeVillage: this.$root.$data.activeVillage,
|
activeVillageState: this.$root.$data.activeVillageState,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -49,7 +48,7 @@ export default {
|
|||||||
},
|
},
|
||||||
isThisVillageTask(task) {
|
isThisVillageTask(task) {
|
||||||
const taskVillageId = (task.args || {}).villageId;
|
const taskVillageId = (task.args || {}).villageId;
|
||||||
const currentVillageId = this.activeVillage.id;
|
const currentVillageId = this.activeVillageState.id;
|
||||||
return taskVillageId !== undefined && taskVillageId === currentVillageId;
|
return taskVillageId !== undefined && taskVillageId === currentVillageId;
|
||||||
},
|
},
|
||||||
onRemove(taskId) {
|
onRemove(taskId) {
|
||||||
|
@ -13,39 +13,57 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<template v-for="village in shared.villages">
|
<template v-for="villageState in shared.villageStates">
|
||||||
<tr class="normal-line top-line">
|
<tr class="normal-line top-line">
|
||||||
<td :class="{ active: village.active }" :title="village.id">{{ village.name }}</td>
|
<td :class="{ active: villageState.village.active }" :title="villageState.id">
|
||||||
<td class="right">
|
{{ villageState.village.name }}
|
||||||
<filling :value="village.lumber" :max="village.warehouse" :speed="village.performance.lumber"></filling>
|
|
||||||
</td>
|
</td>
|
||||||
<td class="right">
|
<td class="right">
|
||||||
<filling :value="village.clay" :max="village.warehouse" :speed="village.performance.clay"></filling>
|
<filling
|
||||||
|
:value="villageState.resources.lumber"
|
||||||
|
:max="villageState.storage.lumber"
|
||||||
|
:speed="villageState.performance.lumber"
|
||||||
|
></filling>
|
||||||
</td>
|
</td>
|
||||||
<td class="right">
|
<td class="right">
|
||||||
<filling :value="village.iron" :max="village.warehouse" :speed="village.performance.iron"></filling>
|
<filling
|
||||||
|
:value="villageState.resources.clay"
|
||||||
|
:max="villageState.storage.clay"
|
||||||
|
:speed="villageState.performance.clay"
|
||||||
|
></filling>
|
||||||
</td>
|
</td>
|
||||||
<td class="right">
|
<td class="right">
|
||||||
<filling :value="village.crop" :max="village.granary" :speed="village.performance.crop"></filling>
|
<filling
|
||||||
|
:value="villageState.resources.iron"
|
||||||
|
:max="villageState.storage.iron"
|
||||||
|
:speed="villageState.performance.iron"
|
||||||
|
></filling>
|
||||||
</td>
|
</td>
|
||||||
<td class="right">
|
<td class="right">
|
||||||
<a :href="warehousePath(village)" v-text="village.warehouse"></a>
|
<filling
|
||||||
|
:value="villageState.resources.crop"
|
||||||
|
:max="villageState.storage.crop"
|
||||||
|
:speed="villageState.performance.crop"
|
||||||
|
></filling>
|
||||||
</td>
|
</td>
|
||||||
<td class="right" v-text="village.granary"></td>
|
<td class="right">
|
||||||
|
<a :href="warehousePath(villageState.village)" v-text="villageState.storage.lumber"></a>
|
||||||
|
</td>
|
||||||
|
<td class="right" v-text="villageState.storage.crop"></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="performance-line">
|
<tr class="performance-line">
|
||||||
<td class="right">Прирост:</td>
|
<td class="right">Прирост:</td>
|
||||||
<td class="right">
|
<td class="right">
|
||||||
<resource :value="village.performance.lumber"></resource>
|
<resource :value="villageState.performance.lumber"></resource>
|
||||||
</td>
|
</td>
|
||||||
<td class="right">
|
<td class="right">
|
||||||
<resource :value="village.performance.clay"></resource>
|
<resource :value="villageState.performance.clay"></resource>
|
||||||
</td>
|
</td>
|
||||||
<td class="right">
|
<td class="right">
|
||||||
<resource :value="village.performance.iron"></resource>
|
<resource :value="villageState.performance.iron"></resource>
|
||||||
</td>
|
</td>
|
||||||
<td class="right">
|
<td class="right">
|
||||||
<resource :value="village.performance.crop"></resource>
|
<resource :value="villageState.performance.crop"></resource>
|
||||||
</td>
|
</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td></td>
|
<td></td>
|
||||||
@ -54,7 +72,7 @@
|
|||||||
<td class="right">След:</td>
|
<td class="right">След:</td>
|
||||||
<td class="right">
|
<td class="right">
|
||||||
<resource
|
<resource
|
||||||
:value="village.requiredResources.lumber"
|
:value="villageState.required.resources.lumber"
|
||||||
:hide-zero="true"
|
:hide-zero="true"
|
||||||
:color="false"
|
:color="false"
|
||||||
:sign="false"
|
:sign="false"
|
||||||
@ -62,7 +80,7 @@
|
|||||||
</td>
|
</td>
|
||||||
<td class="right">
|
<td class="right">
|
||||||
<resource
|
<resource
|
||||||
:value="village.requiredResources.clay"
|
:value="villageState.required.resources.clay"
|
||||||
:hide-zero="true"
|
:hide-zero="true"
|
||||||
:color="false"
|
:color="false"
|
||||||
:sign="false"
|
:sign="false"
|
||||||
@ -70,7 +88,7 @@
|
|||||||
</td>
|
</td>
|
||||||
<td class="right">
|
<td class="right">
|
||||||
<resource
|
<resource
|
||||||
:value="village.requiredResources.iron"
|
:value="villageState.required.resources.iron"
|
||||||
:hide-zero="true"
|
:hide-zero="true"
|
||||||
:color="false"
|
:color="false"
|
||||||
:sign="false"
|
:sign="false"
|
||||||
@ -78,62 +96,79 @@
|
|||||||
</td>
|
</td>
|
||||||
<td class="right">
|
<td class="right">
|
||||||
<resource
|
<resource
|
||||||
:value="village.requiredResources.crop"
|
:value="villageState.required.resources.crop"
|
||||||
:hide-zero="true"
|
:hide-zero="true"
|
||||||
:color="false"
|
:color="false"
|
||||||
:sign="false"
|
:sign="false"
|
||||||
></resource>
|
></resource>
|
||||||
</td>
|
</td>
|
||||||
<td class="right" v-text="secondsToTime(village.buildRemainingSeconds)"></td>
|
<td class="right" v-text="secondsToRequiredTime(villageState.buildRemainingSeconds)"></td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="required-line">
|
<tr class="required-line">
|
||||||
<td class="right">Баланс:</td>
|
<td class="right">Баланс:</td>
|
||||||
<td class="right">
|
<td class="right">
|
||||||
<resource :value="village.requiredBalance.lumber"></resource>
|
<resource :value="villageState.required.balance.lumber"></resource>
|
||||||
</td>
|
</td>
|
||||||
<td class="right">
|
<td class="right">
|
||||||
<resource :value="village.requiredBalance.clay"></resource>
|
<resource :value="villageState.required.balance.clay"></resource>
|
||||||
</td>
|
</td>
|
||||||
<td class="right">
|
<td class="right">
|
||||||
<resource :value="village.requiredBalance.iron"></resource>
|
<resource :value="villageState.required.balance.iron"></resource>
|
||||||
</td>
|
</td>
|
||||||
<td class="right">
|
<td class="right">
|
||||||
<resource :value="village.requiredBalance.crop"></resource>
|
<resource :value="villageState.required.balance.crop"></resource>
|
||||||
</td>
|
</td>
|
||||||
<td class="right" v-text="timeToRequired(village)"></td>
|
<td class="right" v-text="secondsToRequiredTime(villageState.required.time)"></td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="required-line">
|
<tr class="required-line">
|
||||||
<td class="right">Баланс очереди:</td>
|
<td class="right">Баланс очереди:</td>
|
||||||
<td class="right">
|
<td class="right">
|
||||||
<resource :value="village.totalRequiredBalance.lumber"></resource>
|
<resource :value="villageState.totalRequired.balance.lumber"></resource>
|
||||||
</td>
|
</td>
|
||||||
<td class="right">
|
<td class="right">
|
||||||
<resource :value="village.totalRequiredBalance.clay"></resource>
|
<resource :value="villageState.totalRequired.balance.clay"></resource>
|
||||||
</td>
|
</td>
|
||||||
<td class="right">
|
<td class="right">
|
||||||
<resource :value="village.totalRequiredBalance.iron"></resource>
|
<resource :value="villageState.totalRequired.balance.iron"></resource>
|
||||||
</td>
|
</td>
|
||||||
<td class="right">
|
<td class="right">
|
||||||
<resource :value="village.totalRequiredBalance.crop"></resource>
|
<resource :value="villageState.totalRequired.balance.crop"></resource>
|
||||||
</td>
|
</td>
|
||||||
<td class="right" v-text="timeToTotalRequired(village)"></td>
|
<td class="right" v-text="secondsToRequiredTime(villageState.totalRequired.time)"></td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
<tr class="commitments-line">
|
||||||
|
<td class="right">Обязательства:</td>
|
||||||
|
<td class="right">
|
||||||
|
<resource :value="villageState.commitments.lumber" :hide-zero="true"></resource>
|
||||||
|
</td>
|
||||||
|
<td class="right">
|
||||||
|
<resource :value="villageState.commitments.clay" :hide-zero="true"></resource>
|
||||||
|
</td>
|
||||||
|
<td class="right">
|
||||||
|
<resource :value="villageState.commitments.iron" :hide-zero="true"></resource>
|
||||||
|
</td>
|
||||||
|
<td class="right">
|
||||||
|
<resource :value="villageState.commitments.crop" :hide-zero="true"></resource>
|
||||||
|
</td>
|
||||||
|
<td></td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="incoming-line">
|
<tr class="incoming-line">
|
||||||
<td class="right">Торговцы:</td>
|
<td class="right">Торговцы:</td>
|
||||||
<td class="right">
|
<td class="right">
|
||||||
<resource :value="village.incomingResources.lumber" :hide-zero="true"></resource>
|
<resource :value="villageState.incomingResources.lumber" :hide-zero="true"></resource>
|
||||||
</td>
|
</td>
|
||||||
<td class="right">
|
<td class="right">
|
||||||
<resource :value="village.incomingResources.clay" :hide-zero="true"></resource>
|
<resource :value="villageState.incomingResources.clay" :hide-zero="true"></resource>
|
||||||
</td>
|
</td>
|
||||||
<td class="right">
|
<td class="right">
|
||||||
<resource :value="village.incomingResources.iron" :hide-zero="true"></resource>
|
<resource :value="villageState.incomingResources.iron" :hide-zero="true"></resource>
|
||||||
</td>
|
</td>
|
||||||
<td class="right">
|
<td class="right">
|
||||||
<resource :value="village.incomingResources.crop" :hide-zero="true"></resource>
|
<resource :value="villageState.incomingResources.crop" :hide-zero="true"></resource>
|
||||||
</td>
|
</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td></td>
|
<td></td>
|
||||||
@ -143,14 +178,14 @@
|
|||||||
<td class="right" colspan="6">
|
<td class="right" colspan="6">
|
||||||
<a
|
<a
|
||||||
class="village-quick-link"
|
class="village-quick-link"
|
||||||
v-for="v in shared.villages"
|
v-for="s in shared.villageStates"
|
||||||
v-if="v.id !== village.id"
|
v-if="s.id !== villageState.id"
|
||||||
:href="marketPath(village, v)"
|
:href="marketPath(villageState.village, s.village)"
|
||||||
:title="'Отправить ресурсы из ' + village.name + ' в ' + v.name"
|
:title="'Отправить ресурсы из ' + villageState.village.name + ' в ' + s.village.name"
|
||||||
>->{{ v.name }}</a
|
>->{{ s.village.name }}</a
|
||||||
>
|
>
|
||||||
<a class="village-quick-link" :href="quartersPath(village)">Казармы</a>
|
<a class="village-quick-link" :href="quartersPath(villageState.village)">Казармы</a>
|
||||||
<a class="village-quick-link" :href="horseStablePath(village)">Конюшни</a>
|
<a class="village-quick-link" :href="horseStablePath(villageState.village)">Конюшни</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</template>
|
</template>
|
||||||
@ -173,7 +208,7 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
shared: this.$root.$data,
|
shared: this.$root.$data,
|
||||||
activeVillage: this.$root.$data.activeVillage,
|
activeVillageState: this.$root.$data.activeVillageState,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@ -213,12 +248,6 @@ export default {
|
|||||||
}
|
}
|
||||||
return this.secondsToTime(value);
|
return this.secondsToTime(value);
|
||||||
},
|
},
|
||||||
timeToRequired(village) {
|
|
||||||
return this.secondsToRequiredTime(village.timeToRequired());
|
|
||||||
},
|
|
||||||
timeToTotalRequired(village) {
|
|
||||||
return this.secondsToRequiredTime(village.timeToTotalRequired());
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
@ -244,6 +273,7 @@ export default {
|
|||||||
|
|
||||||
.performance-line td,
|
.performance-line td,
|
||||||
.required-line td,
|
.required-line td,
|
||||||
|
.commitments-line td,
|
||||||
.incoming-line td {
|
.incoming-line td {
|
||||||
padding: 0 4px 4px;
|
padding: 0 4px 4px;
|
||||||
font-size: 90%;
|
font-size: 90%;
|
||||||
|
@ -6,6 +6,7 @@ export interface Args {
|
|||||||
taskId?: TaskId;
|
taskId?: TaskId;
|
||||||
targetTaskId?: TaskId;
|
targetTaskId?: TaskId;
|
||||||
villageId?: number;
|
villageId?: number;
|
||||||
|
targetVillageId?: number;
|
||||||
buildId?: number;
|
buildId?: number;
|
||||||
categoryId?: number;
|
categoryId?: number;
|
||||||
sheetId?: number;
|
sheetId?: number;
|
||||||
|
@ -133,6 +133,18 @@ export class Scheduler {
|
|||||||
return tasks.reduce((acc, t) => acc.add(t.args.resources!), new Resources(0, 0, 0, 0));
|
return tasks.reduce((acc, t) => acc.add(t.args.resources!), new Resources(0, 0, 0, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getResourceCommitments(villageId: number): Array<number> {
|
||||||
|
const tasks = this.taskQueue
|
||||||
|
.seeItems()
|
||||||
|
.filter(
|
||||||
|
t =>
|
||||||
|
t.name === SendResourcesTask.name &&
|
||||||
|
t.args.villageId === villageId &&
|
||||||
|
t.args.targetVillageId !== undefined
|
||||||
|
);
|
||||||
|
return tasks.map(t => t.args.targetVillageId!);
|
||||||
|
}
|
||||||
|
|
||||||
private reorderVillageTasks(villageId: number) {
|
private reorderVillageTasks(villageId: number) {
|
||||||
const tasks = this.taskQueue.seeItems();
|
const tasks = this.taskQueue.seeItems();
|
||||||
const trainPred = (t: Task) => isTrainTroopTask(t.name) && sameVillage(villageId, t.args);
|
const trainPred = (t: Task) => isTrainTroopTask(t.name) && sameVillage(villageId, t.args);
|
||||||
|
100
src/VillageState.ts
Normal file
100
src/VillageState.ts
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
import { Village } from './Core/Village';
|
||||||
|
import { Scheduler } from './Scheduler';
|
||||||
|
import { Resources } from './Core/Resources';
|
||||||
|
import { VillageStorage } from './Storage/VillageStorage';
|
||||||
|
import { calcGatheringTimings } from './Core/GatheringTimings';
|
||||||
|
|
||||||
|
interface RequiredResources {
|
||||||
|
resources: Resources;
|
||||||
|
balance: Resources;
|
||||||
|
time: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface VillageOwnState {
|
||||||
|
id: number;
|
||||||
|
village: Village;
|
||||||
|
resources: Resources;
|
||||||
|
performance: Resources;
|
||||||
|
required: RequiredResources;
|
||||||
|
totalRequired: RequiredResources;
|
||||||
|
incomingResources: Resources;
|
||||||
|
storage: Resources;
|
||||||
|
buildRemainingSeconds: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface VillageOwnStateDictionary {
|
||||||
|
[id: number]: VillageOwnState;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface VillageState extends VillageOwnState {
|
||||||
|
commitments: Resources;
|
||||||
|
}
|
||||||
|
|
||||||
|
function calcResourceBalance(resources: Resources, current: Resources, performance: Resources): RequiredResources {
|
||||||
|
return {
|
||||||
|
resources: resources,
|
||||||
|
balance: current.sub(resources),
|
||||||
|
time: timeToResources(current, resources, performance),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function timeToResources(current: Resources, desired: Resources, performance: Resources): number {
|
||||||
|
const timings = calcGatheringTimings(current, desired, performance);
|
||||||
|
if (timings.never) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return timings.hours * 3600;
|
||||||
|
}
|
||||||
|
|
||||||
|
function calcIncomingResources(storage: VillageStorage): Resources {
|
||||||
|
return storage.getIncomingMerchants().reduce((m, i) => m.add(i.resources), Resources.zero());
|
||||||
|
}
|
||||||
|
|
||||||
|
function createVillageOwnState(village: Village, scheduler: Scheduler): VillageOwnState {
|
||||||
|
const storage = new VillageStorage(village.id);
|
||||||
|
const resources = storage.getResources();
|
||||||
|
const resourceStorage = storage.getResourceStorage();
|
||||||
|
const performance = storage.getResourcesPerformance();
|
||||||
|
const buildQueueInfo = storage.getBuildingQueueInfo();
|
||||||
|
const requiredResources = scheduler.getVillageRequiredResources(village.id);
|
||||||
|
const totalRequiredResources = scheduler.getTotalVillageRequiredResources(village.id);
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: village.id,
|
||||||
|
village,
|
||||||
|
resources,
|
||||||
|
performance,
|
||||||
|
required: calcResourceBalance(requiredResources, resources, performance),
|
||||||
|
totalRequired: calcResourceBalance(totalRequiredResources, resources, performance),
|
||||||
|
storage: Resources.fromStorage(resourceStorage),
|
||||||
|
buildRemainingSeconds: buildQueueInfo.seconds,
|
||||||
|
incomingResources: calcIncomingResources(storage),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function createVillageOwnStates(villages: Array<Village>, scheduler: Scheduler): VillageOwnStateDictionary {
|
||||||
|
const result: VillageOwnStateDictionary = {};
|
||||||
|
for (let village of villages) {
|
||||||
|
result[village.id] = createVillageOwnState(village, scheduler);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createVillageState(
|
||||||
|
state: VillageOwnState,
|
||||||
|
ownStates: VillageOwnStateDictionary,
|
||||||
|
scheduler: Scheduler
|
||||||
|
): VillageState {
|
||||||
|
const villageIds = scheduler.getResourceCommitments(state.id);
|
||||||
|
const commitments = villageIds.reduce(
|
||||||
|
(res, villageId) => res.add(ownStates[villageId].required.balance),
|
||||||
|
Resources.zero()
|
||||||
|
);
|
||||||
|
return { ...state, commitments };
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createVillageStates(villages: Array<Village>, scheduler: Scheduler): Array<VillageState> {
|
||||||
|
const ownStates = createVillageOwnStates(villages, scheduler);
|
||||||
|
return villages.map(village => createVillageState(ownStates[village.id], ownStates, scheduler));
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user