Improve resources sending
Configure rounding values and postpone timeout
This commit is contained in:
		| @@ -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 }, | ||||
|         ]); | ||||
|   | ||||
| @@ -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)); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
| @@ -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() { | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
| @@ -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; | ||||
|     }); | ||||
| }); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user