Add hero resource switch
This commit is contained in:
		
							
								
								
									
										11
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								README.md
									
									
									
									
									
								
							| @@ -1,12 +1,13 @@ | ||||
| # Travian automation | ||||
|  | ||||
| - [ ] Автоматическая отправка набегов на учетные записи или автоматическая отправка волн атак | ||||
| - [x] Автоматическая отправка героя в приключение | ||||
| - [x] Автоматическое начало строительства зданий и/или ресурсных полей | ||||
| - [ ] Автоматический скан карты | ||||
| - [ ] Автоматический скан статистики других игроков | ||||
| - [ ] Автоматическая отправка ресурсов на другие учетные записи | ||||
| - [x] Автоматическое обучение войск | ||||
| - [x] Автоматическая отправка героя в приключение | ||||
| - [x] Автоматическое переключение ресурсов героя | ||||
| - [ ] Автоматическая отправка набегов на учетные записи или автоматическая отправка волн атак | ||||
| - [ ] Автоматический скан карты | ||||
| - [ ] Автоматическая отправка ресурсов на другие учетные записи | ||||
| - [ ] Автоматическое размещение ставок на аукционе | ||||
| - [ ] Автоматический запуск празднований | ||||
| - [ ] Сканирование статистики других игроков | ||||
| - [ ] Сканирование собственных деревень для отображения ресурсов и информации в одном месте | ||||
|   | ||||
							
								
								
									
										71
									
								
								src/Action/BalanceHeroResourcesAction.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								src/Action/BalanceHeroResourcesAction.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,71 @@ | ||||
| import { ActionController, registerAction } from './ActionController'; | ||||
| import { Args } from '../Common'; | ||||
| import { Task } from '../Storage/TaskQueue'; | ||||
| import { getNumber, trimPrefix } from '../utils'; | ||||
| import { AbortTaskError, ActionError } from '../Errors'; | ||||
|  | ||||
| interface Resource { | ||||
|     type: number; | ||||
|     value: number; | ||||
| } | ||||
|  | ||||
| const ALL = 0; | ||||
|  | ||||
| @registerAction | ||||
| export class BalanceHeroResourcesAction extends ActionController { | ||||
|     async run(args: Args, task: Task): Promise<any> { | ||||
|         const res = this.getResources(); | ||||
|         const currentType = this.getCurrentHeroResource(task); | ||||
|         console.log('RESOURCES', res); | ||||
|         console.log('CURRENT TYPE', currentType); | ||||
|         const sorted = res.sort((x, y) => x.value - y.value); | ||||
|         const min = sorted[0]; | ||||
|         const max = sorted[sorted.length - 1]; | ||||
|         const delta = max.value - min.value; | ||||
|         const eps = max.value / 10; | ||||
|         console.log('MIN', min, 'MAX', max, 'DELTA', delta, 'EPS', eps); | ||||
|         const resType = delta > eps ? min.type : ALL; | ||||
|         if (resType !== currentType) { | ||||
|             this.changeToHeroResource(task, resType); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private getResources(): Array<Resource> { | ||||
|         const res = this.state.get('resources'); | ||||
|         const resList: Array<Resource> = []; | ||||
|         for (let r in res) { | ||||
|             const type = getNumber(r); | ||||
|             const value = getNumber(res[r]); | ||||
|             resList.push({ type, value }); | ||||
|         } | ||||
|         return resList; | ||||
|     } | ||||
|  | ||||
|     private getCurrentHeroResource(task: Task): number { | ||||
|         for (let type of [0, 1, 2, 3, 4]) { | ||||
|             const input = jQuery(`#resourceHero${type}`); | ||||
|             if (input.length !== 1) { | ||||
|                 throw new ActionError(task.id, `Hero resource ${type} not found`); | ||||
|             } | ||||
|             if (input.prop('checked')) { | ||||
|                 return type; | ||||
|             } | ||||
|         } | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     private changeToHeroResource(task: Task, type: number) { | ||||
|         const input = jQuery(`#resourceHero${type}`); | ||||
|         if (input.length !== 1) { | ||||
|             throw new ActionError(task.id, `Hero resource ${type} not found`); | ||||
|         } | ||||
|  | ||||
|         const btn = jQuery('#saveHeroAttributes'); | ||||
|         if (btn.length !== 1) { | ||||
|             throw new ActionError(task.id, `Hero resource button not found`); | ||||
|         } | ||||
|  | ||||
|         input.trigger('click'); | ||||
|         btn.trigger('click'); | ||||
|     } | ||||
| } | ||||
| @@ -2,6 +2,7 @@ import { ActionController, registerAction } from './ActionController'; | ||||
| import { Args } from '../Common'; | ||||
| import { Task } from '../Storage/TaskQueue'; | ||||
| import { ActionError } from '../Errors'; | ||||
| import { getNumber } from '../utils'; | ||||
|  | ||||
| @registerAction | ||||
| export class GrabHeroAttributesAction extends ActionController { | ||||
| @@ -10,13 +11,11 @@ export class GrabHeroAttributesAction extends ActionController { | ||||
|         if (healthElement.length !== 1) { | ||||
|             throw new ActionError(task.id, 'Health dom element not found'); | ||||
|         } | ||||
|  | ||||
|         const text = healthElement.text(); | ||||
|         let normalized = text.replace(/[^0-9]/g, ''); | ||||
|         const value = Number(normalized); | ||||
|         if (isNaN(value)) { | ||||
|             throw new ActionError(task.id, `Health value "${text}" (${normalized}) couldn't be converted to number`); | ||||
|         } | ||||
|  | ||||
|         const value = getNumber(normalized); | ||||
|         this.state.set('hero', { health: value }); | ||||
|     } | ||||
| } | ||||
|   | ||||
							
								
								
									
										36
									
								
								src/Action/GrabVillageResourcesAction.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/Action/GrabVillageResourcesAction.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | ||||
| import { ActionController, registerAction } from './ActionController'; | ||||
| import { Args } from '../Common'; | ||||
| import { Task } from '../Storage/TaskQueue'; | ||||
| import { getNumber } from '../utils'; | ||||
| import { ActionError } from '../Errors'; | ||||
|  | ||||
| const LUMBER = 1; | ||||
| const CLAY = 2; | ||||
| const IRON = 3; | ||||
| const CROP = 4; | ||||
|  | ||||
| @registerAction | ||||
| export class GrabVillageResourcesAction extends ActionController { | ||||
|     async run(args: Args, task: Task): Promise<any> { | ||||
|         const lumber = this.grabResource(task, LUMBER); | ||||
|         const clay = this.grabResource(task, CLAY); | ||||
|         const iron = this.grabResource(task, IRON); | ||||
|         const crop = this.grabResource(task, CROP); | ||||
|  | ||||
|         this.state.set('resources', { [LUMBER]: lumber, [CLAY]: clay, [IRON]: iron, [CROP]: crop }); | ||||
|     } | ||||
|  | ||||
|     private grabResource(task: Task, type: number): number { | ||||
|         const stockBarElement = jQuery('#stockBar'); | ||||
|         if (stockBarElement.length !== 1) { | ||||
|             throw new ActionError(task.id, 'Stock Bar not found'); | ||||
|         } | ||||
|  | ||||
|         const resElement = stockBarElement.find(`#l${type}`); | ||||
|         if (resElement.length !== 1) { | ||||
|             throw new ActionError(task.id, `Resource #${type} not found`); | ||||
|         } | ||||
|  | ||||
|         return getNumber(resElement.text().replace(/[^0-9]/g, '')); | ||||
|     } | ||||
| } | ||||
| @@ -22,7 +22,7 @@ export class TrainTrooperAction extends ActionController { | ||||
|  | ||||
|         const maxCount = getNumber(countLink.text()); | ||||
|         if (maxCount < trainCount) { | ||||
|             throw new TryLaterError(task.id, 10 * 60, `Max count ${maxCount} less then need ${trainCount}`); | ||||
|             throw new TryLaterError(task.id, 20 * 60, `Max count ${maxCount} less then need ${trainCount}`); | ||||
|         } | ||||
|  | ||||
|         const input = block.find(`input[name="t${troopId}"]`); | ||||
|   | ||||
| @@ -9,6 +9,7 @@ import { createAction } from './Action/ActionController'; | ||||
| import { createTask } from './Task/TaskController'; | ||||
| import { SendOnAdventureTask } from './Task/SendOnAdventureTask'; | ||||
| import { GameState } from './Storage/GameState'; | ||||
| import { BalanceHeroResourcesTask } from './Task/BalanceHeroResourcesTask'; | ||||
|  | ||||
| export class Scheduler { | ||||
|     private readonly version: string; | ||||
| @@ -33,8 +34,11 @@ export class Scheduler { | ||||
|         this.scheduleHeroAdventure(); | ||||
|         setInterval(() => this.scheduleHeroAdventure(), 3600 * 1000); | ||||
|  | ||||
|         this.scheduleResGrab(); | ||||
|         setInterval(() => this.scheduleResGrab(), 600 * 1000); | ||||
|  | ||||
|         while (true) { | ||||
|             await this.doLoopStep(); | ||||
|             await this.doTaskProcessingStep(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -49,7 +53,13 @@ export class Scheduler { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private async doLoopStep() { | ||||
|     private scheduleResGrab() { | ||||
|         if (!this.taskQueue.hasNamed(BalanceHeroResourcesTask.name)) { | ||||
|             this.taskQueue.push(new Command(BalanceHeroResourcesTask.name, {}), timestamp()); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private async doTaskProcessingStep() { | ||||
|         await sleepShort(); | ||||
|         const currentTs = timestamp(); | ||||
|         const taskCommand = this.taskQueue.get(currentTs); | ||||
|   | ||||
							
								
								
									
										22
									
								
								src/Task/BalanceHeroResourcesTask.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/Task/BalanceHeroResourcesTask.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| import { Args, Command } from '../Common'; | ||||
| import { Task } from '../Storage/TaskQueue'; | ||||
| import { TaskController, registerTask } from './TaskController'; | ||||
| import { GoToPageAction } from '../Action/GoToPageAction'; | ||||
| import { CompleteTaskAction } from '../Action/CompleteTaskAction'; | ||||
| import { TrainTrooperAction } from '../Action/TrainTrooperAction'; | ||||
| import { GrabVillageResourcesAction } from '../Action/GrabVillageResourcesAction'; | ||||
| import { BalanceHeroResourcesAction } from '../Action/BalanceHeroResourcesAction'; | ||||
|  | ||||
| @registerTask | ||||
| export class BalanceHeroResourcesTask extends TaskController { | ||||
|     async run(task: Task) { | ||||
|         const args: Args = { ...task.cmd.args, taskId: task.id }; | ||||
|         this.scheduler.scheduleActions([ | ||||
|             new Command(GoToPageAction.name, { ...args, path: '/dorf1.php' }), | ||||
|             new Command(GrabVillageResourcesAction.name, args), | ||||
|             new Command(GoToPageAction.name, { ...args, path: 'hero.php' }), | ||||
|             new Command(BalanceHeroResourcesAction.name, args), | ||||
|             new Command(CompleteTaskAction.name, args), | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
| @@ -4,7 +4,6 @@ import { Scheduler } from '../Scheduler'; | ||||
| const taskMap: { [name: string]: Function | undefined } = {}; | ||||
|  | ||||
| export function registerTask(constructor: Function) { | ||||
|     console.log('REGISTER TASK', constructor.name); | ||||
|     taskMap[constructor.name] = constructor; | ||||
| } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user