Improve resources sending

Configure rounding values and postpone timeout
This commit is contained in:
Anton Vakhrushev 2020-05-17 22:16:01 +03:00
parent 0625abd4eb
commit 3b34e06a7d
7 changed files with 90 additions and 14 deletions

View File

@ -92,23 +92,28 @@ export class SendResourcesAction extends ActionController {
}
private getResourcesForTransfer(senderState: VillageState, recipientState: VillageState): Resources {
const multiplier = senderState.settings.sendResourcesMultiplier;
const timeout = senderState.settings.sendResourcesTimeout;
const senderReadySendResources = this.getSenderAvailableResources(senderState);
const recipientNeedsResources = this.getRecipientRequirements(recipientState, timeout);
const contractResources = senderReadySendResources.min(recipientNeedsResources);
const senderReadyResources = this.getSenderAvailableResources(senderState).downTo(multiplier);
const recipientNeedResources = this.getRecipientRequirements(recipientState, timeout).upTo(multiplier);
const contractResources = senderReadyResources.min(recipientNeedResources);
const merchantsCapacity = this.getMerchantsCapacity(timeout);
let readyToTransfer = contractResources;
if (contractResources.amount() > merchantsCapacity) {
const merchantScale = merchantsCapacity / contractResources.amount();
readyToTransfer = contractResources.scale(merchantScale);
readyToTransfer = contractResources.scale(merchantScale).downTo(multiplier);
}
if (readyToTransfer.empty()) {
throw new TryLaterError(aroundMinutes(timeout), 'Not enough resources to transfer');
}
console.log('Merchants capacity', merchantsCapacity);
console.table([
{ name: 'Sender', ...senderReadySendResources },
{ name: 'Recipient', ...recipientNeedsResources },
{ name: 'Sender', ...senderReadyResources },
{ name: 'Recipient', ...recipientNeedResources },
{ name: 'Prepared', ...contractResources },
{ name: 'Ready to transfer', ...readyToTransfer },
]);

View File

@ -118,4 +118,33 @@ export class Resources implements ResourcesInterface {
empty(): boolean {
return this.eq(Resources.zero());
}
upTo(multiplier: number): Resources {
const upper = (v: number) => {
if (v === 0) {
return v;
}
if (v % multiplier === 0) {
return v;
}
return (Math.floor(v / multiplier) + 1) * multiplier;
};
return new Resources(upper(this.lumber), upper(this.clay), upper(this.iron), upper(this.crop));
}
downTo(multiplier: number): Resources {
const lower = (v: number) => {
if (v === 0) {
return v;
}
if (v % multiplier === 0) {
return v;
}
const part = Math.floor(v / multiplier);
return part * multiplier;
};
return new Resources(lower(this.lumber), lower(this.clay), lower(this.iron), lower(this.crop));
}
}

View File

@ -40,9 +40,11 @@ export type VillageList = Array<Village>;
export interface VillageSettings {
sendResourcesThreshold: number;
sendResourcesTimeout: number;
sendResourcesMultiplier: number;
}
export const VillageSettingsDefaults: VillageSettings = {
sendResourcesTimeout: 15,
sendResourcesThreshold: 100,
sendResourcesMultiplier: 10,
} as const;

View File

@ -14,6 +14,7 @@ export enum Mutations {
SetVillageSettings = 'set_village_settings',
UpdateVillageSendResourceThreshold = 'UpdateVillageSendResourceThreshold',
UpdateVillageSendResourceTimeout = 'UpdateVillageSendResourceTimeout',
UpdateVillageSendResourcesMultiplier = 'UpdateVillageSendResourcesMultiplier',
}
export enum Actions {
@ -34,6 +35,7 @@ export function createStore(villageStateRepository: VillageStateRepository) {
villageName: '',
sendResourcesThreshold: 0,
sendResourcesTimeout: 0,
sendResourcesMultiplier: 0,
},
},
getters: {
@ -66,6 +68,9 @@ export function createStore(villageStateRepository: VillageStateRepository) {
[Mutations.UpdateVillageSendResourceTimeout](state, value) {
state.villageSettings.sendResourcesTimeout = getNumber(value);
},
[Mutations.UpdateVillageSendResourcesMultiplier](state, value) {
state.villageSettings.sendResourcesMultiplier = getNumber(value);
},
},
actions: {
[Actions.OpenVillageEditor]({ commit }, { villageId }) {
@ -76,6 +81,7 @@ export function createStore(villageStateRepository: VillageStateRepository) {
villageName: state.village.name,
sendResourcesThreshold: settings.sendResourcesThreshold,
sendResourcesTimeout: settings.sendResourcesTimeout,
sendResourcesMultiplier: settings.sendResourcesMultiplier,
});
commit(Mutations.ToggleVillageEditor, true);
},
@ -87,6 +93,9 @@ export function createStore(villageStateRepository: VillageStateRepository) {
state.villageSettings.sendResourcesThreshold || VillageSettingsDefaults.sendResourcesThreshold,
sendResourcesTimeout:
state.villageSettings.sendResourcesTimeout || VillageSettingsDefaults.sendResourcesTimeout,
sendResourcesMultiplier:
state.villageSettings.sendResourcesMultiplier ||
VillageSettingsDefaults.sendResourcesMultiplier,
};
const storage = new VillageStorage(villageId);
storage.storeSettings(newSettings);

View File

@ -13,6 +13,10 @@
<label class="label" title="Таймаут отправки (мин)">Таймаут отправки (мин)</label>
<input class="input" type="text" v-model="sendResourcesTimeout" />
</div>
<div class="form-input">
<label class="label" title="Множитель отправки (up to)">Множитель отправки (up to)</label>
<input class="input" type="text" v-model="sendResourcesMultiplier" />
</div>
<div class="form-actions">
<button class="btn">Сохранить</button>
</div>
@ -45,6 +49,14 @@ export default {
this.$store.commit(Mutations.UpdateVillageSendResourceTimeout, value);
},
},
sendResourcesMultiplier: {
get() {
return this.$store.state.villageSettings.sendResourcesMultiplier;
},
set(value) {
this.$store.commit(Mutations.UpdateVillageSendResourcesMultiplier, value);
},
},
},
methods: {
close() {

View File

@ -231,14 +231,13 @@ export default {
villageHint(villageState) {
const id = villageState.id;
const name = villageState.village.name;
const timeout = villageState.settings.sendResourcesTimeout;
const threshold = villageState.settings.sendResourcesThreshold;
return `${name}, ${id}, отправка ${timeout} мин, порог ${threshold}`;
return `${name}, ${id}`;
},
villageStatus(villageState) {
const timeout = villageState.settings.sendResourcesTimeout;
const threshold = villageState.settings.sendResourcesThreshold;
return `отправка ${timeout} мин, порог ${threshold}`;
const multiplier = villageState.settings.sendResourcesMultiplier;
return `отправка ${timeout} мин, порог ${threshold}, множ. ${multiplier}`;
},
path(name, args) {
return path(name, args);

View File

@ -7,24 +7,44 @@ describe('Resources', function() {
it('Can compare with lt', function() {
const x = new Resources(0, 0, 0, 0);
const y = new Resources(5, 5, 5, 5);
expect(true).is.equals(x.lt(y));
expect(x.lt(y)).is.true;
});
it('Can compare with lt (mixed)', function() {
const x = new Resources(20, 20, 5, 20);
const y = new Resources(10, 10, 10, 10);
expect(true).is.equals(x.lt(y));
expect(x.lt(y)).is.true;
});
it('Can compare with gt', function() {
const x = new Resources(5, 5, 5, 5);
const y = new Resources(0, 0, 0, 0);
expect(true).is.equals(x.gt(y));
expect(x.gt(y)).is.true;
});
it('Can compare with gt (mixed)', function() {
const x = new Resources(30, 30, 10, 30);
const y = new Resources(20, 20, 20, 20);
expect(false).is.equals(x.gt(y));
expect(x.gt(y)).is.false;
});
it('Can up to 1', function() {
const resources = new Resources(0, 4, 10, 18);
const upped = resources.upTo(1);
expect(upped.eq(resources)).is.true;
});
it('Can up to 10', function() {
const resources = new Resources(0, 4, 10, 18);
const expected = new Resources(0, 10, 10, 20);
const upped = resources.upTo(10);
expect(upped.eq(expected)).is.true;
});
it('Can down to 10', function() {
const resources = new Resources(0, 4, 10, 18);
const expected = new Resources(0, 0, 10, 10);
const lowed = resources.downTo(10);
expect(lowed.eq(expected)).is.true;
});
});