Add fast resource transfer management
This commit is contained in:
parent
f648f7dd5a
commit
304c192ab0
@ -4,7 +4,6 @@ import { Resources } from '../Core/Resources';
|
|||||||
import { Coordinates, Village } from '../Core/Village';
|
import { Coordinates, Village } from '../Core/Village';
|
||||||
import { grabVillageResources } from '../Page/ResourcesBlock';
|
import { grabVillageResources } from '../Page/ResourcesBlock';
|
||||||
import { grabActiveVillageId, grabVillageList } from '../Page/VillageBlock';
|
import { grabActiveVillageId, grabVillageList } from '../Page/VillageBlock';
|
||||||
import { SendResourcesTask } from '../Task/SendResourcesTask';
|
|
||||||
import { aroundMinutes, timestamp } from '../utils';
|
import { aroundMinutes, timestamp } from '../utils';
|
||||||
import { VillageStorage } from '../Storage/VillageStorage';
|
import { VillageStorage } from '../Storage/VillageStorage';
|
||||||
import { Args } from '../Queue/Args';
|
import { Args } from '../Queue/Args';
|
||||||
@ -16,34 +15,18 @@ const TIMEOUT = 15;
|
|||||||
@registerAction
|
@registerAction
|
||||||
export class SendResourcesAction extends ActionController {
|
export class SendResourcesAction extends ActionController {
|
||||||
async run(args: Args, task: Task): Promise<any> {
|
async run(args: Args, task: Task): Promise<any> {
|
||||||
const resources = Resources.fromObject(args.resources || err('No resources'));
|
|
||||||
const coordinates = Coordinates.fromObject(args.coordinates || err('No coordinates'));
|
const coordinates = Coordinates.fromObject(args.coordinates || err('No coordinates'));
|
||||||
|
|
||||||
console.log('Send', resources, 'to', coordinates);
|
|
||||||
|
|
||||||
const recipientVillage = args.targetVillageId
|
const recipientVillage = args.targetVillageId
|
||||||
? this.findRecipientVillageById(args.targetVillageId)
|
? this.findRecipientVillageById(args.targetVillageId)
|
||||||
: this.findRecipientVillage(coordinates);
|
: this.findRecipientVillage(coordinates);
|
||||||
|
|
||||||
const readyToTransfer = this.getResourcesForTransfer(recipientVillage.id).min(resources);
|
const readyToTransfer = this.getResourcesForTransfer(recipientVillage.id);
|
||||||
|
|
||||||
const remainingResources = resources.sub(readyToTransfer).max(Resources.zero());
|
|
||||||
|
|
||||||
console.log('Total res', resources);
|
|
||||||
console.log('To transfer res', readyToTransfer);
|
console.log('To transfer res', readyToTransfer);
|
||||||
console.log('Remaining res', remainingResources);
|
|
||||||
|
|
||||||
if (!remainingResources.empty()) {
|
// Schedule recurrent task
|
||||||
console.log('Schedule next', remainingResources);
|
this.scheduler.scheduleTask(task.name, task.args, timestamp() + aroundMinutes(TIMEOUT));
|
||||||
this.scheduler.scheduleTask(
|
|
||||||
SendResourcesTask.name,
|
|
||||||
{
|
|
||||||
...args,
|
|
||||||
resources: remainingResources,
|
|
||||||
},
|
|
||||||
timestamp() + aroundMinutes(TIMEOUT)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
fillSendResourcesForm(readyToTransfer, coordinates);
|
fillSendResourcesForm(readyToTransfer, coordinates);
|
||||||
clickSendButton();
|
clickSendButton();
|
||||||
|
@ -41,6 +41,8 @@ interface GameState {
|
|||||||
removeTask(taskId: string): void;
|
removeTask(taskId: string): void;
|
||||||
refreshVillages(): void;
|
refreshVillages(): void;
|
||||||
pause(): void;
|
pause(): void;
|
||||||
|
scheduleResourceTransferTasks(fromVillageId: number, toVillageId: number): void;
|
||||||
|
dropResourceTransferTasks(fromVillageId: number, toVillageId: number): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ControlPanel {
|
export class ControlPanel {
|
||||||
@ -101,6 +103,14 @@ export class ControlPanel {
|
|||||||
pause() {
|
pause() {
|
||||||
executionState.setExecutionSettings({ pauseTs: timestamp() + 120 });
|
executionState.setExecutionSettings({ pauseTs: timestamp() + 120 });
|
||||||
},
|
},
|
||||||
|
|
||||||
|
scheduleResourceTransferTasks(fromVillageId: number, toVillageId: number): void {
|
||||||
|
scheduler.scheduleResourceTransferTasks(fromVillageId, toVillageId);
|
||||||
|
},
|
||||||
|
|
||||||
|
dropResourceTransferTasks(fromVillageId: number, toVillageId: number): void {
|
||||||
|
scheduler.dropResourceTransferTasks(fromVillageId, toVillageId);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
state.refresh();
|
state.refresh();
|
||||||
@ -109,11 +119,7 @@ export class ControlPanel {
|
|||||||
state.refresh();
|
state.refresh();
|
||||||
}, 3000);
|
}, 3000);
|
||||||
|
|
||||||
DataStorage.onChange(
|
DataStorage.onChange(() => state.refresh());
|
||||||
_.debounce(() => {
|
|
||||||
state.refresh();
|
|
||||||
}, 500)
|
|
||||||
);
|
|
||||||
|
|
||||||
const getBuildingsInQueue = () =>
|
const getBuildingsInQueue = () =>
|
||||||
this.scheduler
|
this.scheduler
|
||||||
|
@ -172,7 +172,15 @@
|
|||||||
class="village-quick-link"
|
class="village-quick-link"
|
||||||
:class="{ active: villageState.shipment.includes(s.id) }"
|
:class="{ active: villageState.shipment.includes(s.id) }"
|
||||||
:href="marketPath(villageState.village, s.village)"
|
:href="marketPath(villageState.village, s.village)"
|
||||||
:title="'Отправить ресурсы из ' + villageState.village.name + ' в ' + s.village.name"
|
:title="
|
||||||
|
'Отправить ресурсы из ' +
|
||||||
|
villageState.village.name +
|
||||||
|
' в ' +
|
||||||
|
s.village.name +
|
||||||
|
'(shift+click - настроить отправку)'
|
||||||
|
"
|
||||||
|
v-on:click.prevent.shift.exact="setupResourceTransfer(villageState, s)"
|
||||||
|
v-on:click.prevent.exact="goToMarket(villageState.village, s.village)"
|
||||||
>$->{{ s.village.name }}</a
|
>$->{{ s.village.name }}</a
|
||||||
>
|
>
|
||||||
<a class="village-quick-link" :href="quartersPath(villageState.village)">Казармы</a>
|
<a class="village-quick-link" :href="quartersPath(villageState.village)">Казармы</a>
|
||||||
@ -253,6 +261,20 @@ export default {
|
|||||||
}
|
}
|
||||||
return secondsToTime(value.seconds);
|
return secondsToTime(value.seconds);
|
||||||
},
|
},
|
||||||
|
goToMarket(fromVillage, toVillage) {
|
||||||
|
window.location.assign(this.marketPath(fromVillage, toVillage));
|
||||||
|
},
|
||||||
|
setupResourceTransfer(villageState, toVillageState) {
|
||||||
|
villageState.shipment.includes(toVillageState.id)
|
||||||
|
? this.dropResourceTransferTasks(villageState.id, toVillageState.id)
|
||||||
|
: this.scheduleResourceTransferTasks(villageState.id, toVillageState.id);
|
||||||
|
},
|
||||||
|
scheduleResourceTransferTasks(fromVillageId, toVillageId) {
|
||||||
|
this.shared.scheduleResourceTransferTasks(fromVillageId, toVillageId);
|
||||||
|
},
|
||||||
|
dropResourceTransferTasks(fromVillageId, toVillageId) {
|
||||||
|
this.shared.dropResourceTransferTasks(fromVillageId, toVillageId);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
@ -5,23 +5,17 @@ import { IncomingMerchant } from '../../Core/Market';
|
|||||||
import { grabResourcesFromList } from './BuildingPage';
|
import { grabResourcesFromList } from './BuildingPage';
|
||||||
|
|
||||||
interface SendResourcesClickHandler {
|
interface SendResourcesClickHandler {
|
||||||
(resources: Resources, crd: Coordinates, scale: number): void;
|
(resources: Resources, crd: Coordinates): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createSendResourcesButton(onClickHandler: SendResourcesClickHandler) {
|
export function createSendResourcesButton(onClickHandler: SendResourcesClickHandler) {
|
||||||
const id1 = uniqId();
|
const id = uniqId();
|
||||||
const id10 = uniqId();
|
|
||||||
const id100 = uniqId();
|
|
||||||
const id1000 = uniqId();
|
|
||||||
|
|
||||||
jQuery('#button').before(`<div style="padding: 8px">
|
jQuery('#button').before(`<div style="padding: 8px">
|
||||||
<a id="${id1}" href="#">Отправить</a> /
|
<a id="${id}" href="#">Отправить</a> /
|
||||||
<a id="${id10}" href="#">x10</a> /
|
|
||||||
<a id="${id100}" href="#">x100</a> /
|
|
||||||
<a id="${id1000}" href="#">x1000</a>
|
|
||||||
</div>`);
|
</div>`);
|
||||||
|
|
||||||
const createHandler = (handler: SendResourcesClickHandler, scale: number) => (evt: JQuery.Event) => {
|
const createHandler = () => (evt: JQuery.Event) => {
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
const sendSelect = jQuery('#send_select');
|
const sendSelect = jQuery('#send_select');
|
||||||
const resources = new Resources(
|
const resources = new Resources(
|
||||||
@ -31,13 +25,10 @@ export function createSendResourcesButton(onClickHandler: SendResourcesClickHand
|
|||||||
getNumber(sendSelect.find('#r4').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, scale);
|
onClickHandler(resources, crd);
|
||||||
};
|
};
|
||||||
|
|
||||||
jQuery(`#${id1}`).on('click', createHandler(onClickHandler, 1));
|
jQuery(`#${id}`).on('click', createHandler());
|
||||||
jQuery(`#${id10}`).on('click', createHandler(onClickHandler, 10));
|
|
||||||
jQuery(`#${id100}`).on('click', createHandler(onClickHandler, 100));
|
|
||||||
jQuery(`#${id1000}`).on('click', createHandler(onClickHandler, 1000));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function grabMerchantsInfo() {
|
export function grabMerchantsInfo() {
|
||||||
|
@ -56,7 +56,7 @@ export class BuildingPageController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isMarketSendResourcesPage()) {
|
if (isMarketSendResourcesPage()) {
|
||||||
createSendResourcesButton((res, crd, scale) => this.onSendResources(res, crd, scale));
|
createSendResourcesButton((res, crd) => this.onSendResources(res, crd));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isForgePage()) {
|
if (isForgePage()) {
|
||||||
@ -99,7 +99,7 @@ export class BuildingPageController {
|
|||||||
notify(`Training ${count} troopers scheduled`);
|
notify(`Training ${count} troopers scheduled`);
|
||||||
}
|
}
|
||||||
|
|
||||||
private onSendResources(resources: Resources, coordinates: Coordinates, scale: number) {
|
private onSendResources(resources: Resources, coordinates: Coordinates) {
|
||||||
const villageId = grabActiveVillageId();
|
const villageId = grabActiveVillageId();
|
||||||
const targetVillage = grabVillageList().find(v => v.crd.eq(coordinates));
|
const targetVillage = grabVillageList().find(v => v.crd.eq(coordinates));
|
||||||
this.scheduler.scheduleTask(SendResourcesTask.name, {
|
this.scheduler.scheduleTask(SendResourcesTask.name, {
|
||||||
@ -108,10 +108,9 @@ export class BuildingPageController {
|
|||||||
buildTypeId: this.attributes.buildTypeId,
|
buildTypeId: this.attributes.buildTypeId,
|
||||||
buildId: this.attributes.buildId,
|
buildId: this.attributes.buildId,
|
||||||
tabId: this.attributes.tabId,
|
tabId: this.attributes.tabId,
|
||||||
resources: resources.scale(scale),
|
|
||||||
coordinates,
|
coordinates,
|
||||||
});
|
});
|
||||||
notify(`Send resources ${JSON.stringify(resources)} from ${villageId} to ${JSON.stringify(coordinates)}`);
|
notify(`Send resources from ${villageId} to ${JSON.stringify(coordinates)}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
private onResearch(resources: Resources, unitId: number) {
|
private onResearch(resources: Resources, unitId: number) {
|
||||||
|
@ -42,9 +42,11 @@ export class TaskQueue {
|
|||||||
return modifiedCount;
|
return modifiedCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
remove(id: TaskId) {
|
remove(predicate: (t: Task) => boolean): number {
|
||||||
const [_, items] = this.shiftTask(id);
|
const [_, other] = this.split(predicate);
|
||||||
this.flushItems(items);
|
const result = other.length;
|
||||||
|
this.flushItems(other);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
seeItems(): ImmutableTaskList {
|
seeItems(): ImmutableTaskList {
|
||||||
|
@ -13,6 +13,8 @@ import { Args } from './Queue/Args';
|
|||||||
import { ImmutableTaskList, Task, TaskId } from './Queue/TaskProvider';
|
import { ImmutableTaskList, Task, TaskId } from './Queue/TaskProvider';
|
||||||
import { ForgeImprovementTask } from './Task/ForgeImprovementTask';
|
import { ForgeImprovementTask } from './Task/ForgeImprovementTask';
|
||||||
import { getTaskType, TaskType } from './Task/TaskMap';
|
import { getTaskType, TaskType } from './Task/TaskMap';
|
||||||
|
import { MARKET_ID } from './Core/Buildings';
|
||||||
|
import { grabVillageList } from './Page/VillageBlock';
|
||||||
|
|
||||||
export enum ContractType {
|
export enum ContractType {
|
||||||
UpgradeBuilding,
|
UpgradeBuilding,
|
||||||
@ -84,7 +86,7 @@ export class Scheduler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
removeTask(taskId: TaskId) {
|
removeTask(taskId: TaskId) {
|
||||||
this.taskQueue.remove(taskId);
|
this.taskQueue.remove(t => t.id === taskId);
|
||||||
this.actionQueue.clear();
|
this.actionQueue.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,6 +174,30 @@ export class Scheduler {
|
|||||||
return tasks.map(t => t.args.targetVillageId!);
|
return tasks.map(t => t.args.targetVillageId!);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dropResourceTransferTasks(fromVillageId: number, toVillageId: number): void {
|
||||||
|
this.taskQueue.remove(
|
||||||
|
t =>
|
||||||
|
t.name === SendResourcesTask.name &&
|
||||||
|
t.args.villageId === fromVillageId &&
|
||||||
|
t.args.targetVillageId === toVillageId
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
scheduleResourceTransferTasks(fromVillageId: number, toVillageId: number): void {
|
||||||
|
this.dropResourceTransferTasks(fromVillageId, toVillageId);
|
||||||
|
const village = grabVillageList().find(v => v.id === toVillageId);
|
||||||
|
if (!village) {
|
||||||
|
throw new Error('No village');
|
||||||
|
}
|
||||||
|
this.scheduleTask(SendResourcesTask.name, {
|
||||||
|
villageId: fromVillageId,
|
||||||
|
targetVillageId: toVillageId,
|
||||||
|
coordinates: village.crd,
|
||||||
|
buildTypeId: MARKET_ID,
|
||||||
|
tabId: 5,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private reorderVillageTasks(villageId: number) {
|
private reorderVillageTasks(villageId: number) {
|
||||||
const tasks = this.taskQueue.seeItems();
|
const tasks = this.taskQueue.seeItems();
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ describe('Task Queue', function() {
|
|||||||
it('Can remove task by id', 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());
|
const queue = new TaskQueue(provider, new NullLogger());
|
||||||
queue.remove('id1');
|
queue.remove(t => t.id === 'id1');
|
||||||
const tasks = provider.getTasks();
|
const tasks = provider.getTasks();
|
||||||
expect(tasks).to.have.lengthOf(1);
|
expect(tasks).to.have.lengthOf(1);
|
||||||
expect(tasks[0].ts).to.be.equals(2);
|
expect(tasks[0].ts).to.be.equals(2);
|
||||||
|
Loading…
Reference in New Issue
Block a user