diff --git a/src/Action/SendResourcesAction.ts b/src/Action/SendResourcesAction.ts index 8cff452..174fd23 100644 --- a/src/Action/SendResourcesAction.ts +++ b/src/Action/SendResourcesAction.ts @@ -8,9 +8,6 @@ import { Task } from '../Queue/TaskProvider'; import { clickSendButton, fillSendResourcesForm, grabMerchantsInfo } from '../Page/BuildingPage/MarketPage'; import { VillageState } from '../VillageState'; -const TIMEOUT = 15; -const AMOUNT_THRESHOLD = 100; - @registerAction export class SendResourcesAction extends ActionController { async run(args: Args, task: Task): Promise { @@ -29,17 +26,18 @@ export class SendResourcesAction extends ActionController { console.log('To transfer res', readyToTransfer); // Schedule recurrent task - this.scheduler.scheduleTask(task.name, task.args, timestamp() + aroundMinutes(TIMEOUT)); + const timeout = senderVillage.settings.sendResourcesTimeout; + this.scheduler.scheduleTask(task.name, task.args, timestamp() + aroundMinutes(timeout)); fillSendResourcesForm(readyToTransfer, coordinates); clickSendButton(); } - private getMerchantsCapacity(): number { + private getMerchantsCapacity(timeout: number): number { const merchants = grabMerchantsInfo(); const capacity = merchants.available * merchants.carry; if (!capacity) { - throw new TryLaterError(aroundMinutes(TIMEOUT), 'No merchants'); + throw new TryLaterError(aroundMinutes(timeout), 'No merchants'); } return capacity; } @@ -53,13 +51,21 @@ export class SendResourcesAction extends ActionController { { name: 'Sender free', ...free }, ]); - if (free.amount() < AMOUNT_THRESHOLD) { - throw new TryLaterError(aroundMinutes(TIMEOUT), 'Little free resources'); + const amount = free.amount(); + const threshold = senderState.settings.sendResourcesThreshold; + const timeout = senderState.settings.sendResourcesTimeout; + + if (amount < threshold) { + throw new TryLaterError( + aroundMinutes(timeout), + `No free resources (amount ${amount} < threshold ${threshold})` + ); } + return free; } - private getRecipientRequirements(recipientState: VillageState): Resources { + private getRecipientRequirements(recipientState: VillageState, timeout: number): Resources { const maxPossibleToStore = recipientState.storage.capacity.sub(recipientState.performance); const currentResources = recipientState.resources; const incomingResources = recipientState.incomingResources; @@ -79,17 +85,18 @@ export class SendResourcesAction extends ActionController { ]); if (missingResources.empty()) { - throw new TryLaterError(aroundMinutes(TIMEOUT), 'No missing resources'); + throw new TryLaterError(aroundMinutes(timeout), 'No missing resources'); } return missingResources; } private getResourcesForTransfer(senderState: VillageState, recipientState: VillageState): Resources { + const timeout = senderState.settings.sendResourcesTimeout; const senderReadySendResources = this.getSenderAvailableResources(senderState); - const recipientNeedsResources = this.getRecipientRequirements(recipientState); + const recipientNeedsResources = this.getRecipientRequirements(recipientState, timeout); const contractResources = senderReadySendResources.min(recipientNeedsResources); - const merchantsCapacity = this.getMerchantsCapacity(); + const merchantsCapacity = this.getMerchantsCapacity(timeout); let readyToTransfer = contractResources; if (contractResources.amount() > merchantsCapacity) { diff --git a/src/ControlPanel.ts b/src/ControlPanel.ts index 3c46976..ea921bd 100644 --- a/src/ControlPanel.ts +++ b/src/ControlPanel.ts @@ -155,16 +155,16 @@ export class ControlPanel { buildPage.run(); } - this.createControlPanel(state); + this.createControlPanel(state, villageStateRepository); } - private createControlPanel(gameState: GameState) { + private createControlPanel(gameState: GameState, villageStateRepository: VillageStateRepository) { const appId = `app-${uniqId()}`; jQuery('body').prepend(`
`); new Vue({ el: `#${appId}`, data: gameState, - store: createStore(), + store: createStore(villageStateRepository), render: h => h(DashboardApp), }); } diff --git a/src/Core/Village.ts b/src/Core/Village.ts index 4d0eb94..3735c84 100644 --- a/src/Core/Village.ts +++ b/src/Core/Village.ts @@ -37,7 +37,12 @@ export class Village { export type VillageList = Array; -// export interface VillageSettings { -// id: number; -// -// } +export interface VillageSettings { + sendResourcesThreshold: number; + sendResourcesTimeout: number; +} + +export const VillageSettingsDefaults: VillageSettings = { + sendResourcesTimeout: 15, + sendResourcesThreshold: 100, +} as const; diff --git a/src/DashboardView/Dashboard.vue b/src/DashboardView/Dashboard.vue index 2d619f3..bdc1f54 100644 --- a/src/DashboardView/Dashboard.vue +++ b/src/DashboardView/Dashboard.vue @@ -8,8 +8,9 @@
-
+
+
@@ -22,8 +23,10 @@ import VillageStateList from './VillageStateList'; import LogList from './LogList'; import { mapState } from 'vuex'; import { Mutations } from './Store'; +import VillageEditor from './VillageEditor'; export default { components: { + 'village-editor': VillageEditor, 'hdr': Header, 'task-list': TaskList, 'quick-actions': QuickActions, @@ -35,9 +38,15 @@ export default { shared: this.$root.$data, }; }, - computed: mapState({ - isLogsVisible: state => state.views.logs, - }), + computed: { + ...mapState({ + isLogsVisible: state => state.views.logs, + isVillageEditorVisible: state => state.views.villageEditor, + }), + isSecondaryDashboardVisible() { + return this.isLogsVisible || this.isVillageEditorVisible; + }, + }, methods: { toggleLogs() { this.$store.commit(Mutations.toggleLogs); diff --git a/src/DashboardView/Store.ts b/src/DashboardView/Store.ts index c2dcfa9..f669679 100644 --- a/src/DashboardView/Store.ts +++ b/src/DashboardView/Store.ts @@ -1,21 +1,45 @@ import Vuex from 'vuex'; -import { StorageLogRecord } from '../Logger'; import { LogStorage } from '../Storage/LogStorage'; +import { VillageStateRepository } from '../VillageState'; +import { VillageSettings, VillageSettingsDefaults } from '../Core/Village'; +import { getNumber, notify } from '../utils'; +import { VillageStorage } from '../Storage/VillageStorage'; export enum Mutations { showLogs = 'showLogs', hideLogs = 'hideLogs', toggleLogs = 'toggleLogs', updateLogs = 'updateLogs', + ToggleVillageEditor = 'toggle_village_editor', + SetVillageSettings = 'set_village_settings', + UpdateVillageSendResourceThreshold = 'UpdateVillageSendResourceThreshold', + UpdateVillageSendResourceTimeout = 'UpdateVillageSendResourceTimeout', } -export function createStore() { +export enum Actions { + OpenVillageEditor = 'open_village_editor', + SaveVillageSettings = 'save_village_settings', +} + +export function createStore(villageStateRepository: VillageStateRepository) { const store = new Vuex.Store({ state: { views: { + villageEditor: false, logs: false, }, logs: [], + villageSettings: { + villageId: 0, + villageName: '', + sendResourcesThreshold: 0, + sendResourcesTimeout: 0, + }, + }, + getters: { + reverseLogs: state => { + return state.logs.slice().reverse(); + }, }, mutations: { [Mutations.showLogs](state) { @@ -30,10 +54,43 @@ export function createStore() { [Mutations.updateLogs](state, { logs }) { state.logs = logs; }, + [Mutations.ToggleVillageEditor](state, visible?: any) { + state.views.villageEditor = visible === undefined ? !state.views.villageEditor : !!visible; + }, + [Mutations.SetVillageSettings](state, settings) { + state.villageSettings = settings; + }, + [Mutations.UpdateVillageSendResourceThreshold](state, value) { + state.villageSettings.sendResourcesThreshold = getNumber(value); + }, + [Mutations.UpdateVillageSendResourceTimeout](state, value) { + state.villageSettings.sendResourcesTimeout = getNumber(value); + }, }, - getters: { - reverseLogs: state => { - return state.logs.slice().reverse(); + actions: { + [Actions.OpenVillageEditor]({ commit }, { villageId }) { + const state = villageStateRepository.getVillageState(villageId); + const settings = state.settings; + commit(Mutations.SetVillageSettings, { + villageId: state.id, + villageName: state.village.name, + sendResourcesThreshold: settings.sendResourcesThreshold, + sendResourcesTimeout: settings.sendResourcesTimeout, + }); + commit(Mutations.ToggleVillageEditor, true); + }, + [Actions.SaveVillageSettings]({ state }) { + const villageId = state.villageSettings.villageId; + const villageName = state.villageSettings.villageName; + const newSettings: VillageSettings = { + sendResourcesThreshold: + state.villageSettings.sendResourcesThreshold || VillageSettingsDefaults.sendResourcesThreshold, + sendResourcesTimeout: + state.villageSettings.sendResourcesTimeout || VillageSettingsDefaults.sendResourcesTimeout, + }; + const storage = new VillageStorage(villageId); + storage.storeSettings(newSettings); + notify(`Настройки для ${villageName} сохранены`); }, }, }); diff --git a/src/DashboardView/VillageEditor.vue b/src/DashboardView/VillageEditor.vue new file mode 100644 index 0000000..d3b12be --- /dev/null +++ b/src/DashboardView/VillageEditor.vue @@ -0,0 +1,91 @@ + + + + + diff --git a/src/DashboardView/VillageStateList.vue b/src/DashboardView/VillageStateList.vue index a284a25..6a041c4 100644 --- a/src/DashboardView/VillageStateList.vue +++ b/src/DashboardView/VillageStateList.vue @@ -14,8 +14,9 @@