Improve resource contracts updates
This commit is contained in:
		| @@ -1,21 +0,0 @@ | ||||
| import { ActionController, registerAction } from './ActionController'; | ||||
| import { grabContractResources } from '../Page/BuildingPage/BuildingPage'; | ||||
| import { Args } from '../Queue/Args'; | ||||
| import { Task } from '../Queue/TaskProvider'; | ||||
|  | ||||
| @registerAction | ||||
| export class UpdateBuildingTaskResourcesAction extends ActionController { | ||||
|     async run(args: Args, task: Task): Promise<any> { | ||||
|         const buildingTaskId = args.targetTaskId; | ||||
|         if (buildingTaskId === undefined) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         try { | ||||
|             const resources = grabContractResources(); | ||||
|             this.scheduler.updateResources(buildingTaskId, resources); | ||||
|         } catch (e) { | ||||
|             return; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -26,7 +26,7 @@ export class Executor { | ||||
|     constructor(version: string, scheduler: Scheduler, statistics: Statistics) { | ||||
|         this.version = version; | ||||
|         this.scheduler = scheduler; | ||||
|         this.grabbers = new GrabberManager(); | ||||
|         this.grabbers = new GrabberManager(scheduler); | ||||
|         this.statistics = statistics; | ||||
|         this.executionState = new ExecutionStorage(); | ||||
|         this.logger = new ConsoleLogger(this.constructor.name); | ||||
|   | ||||
							
								
								
									
										31
									
								
								src/Grabber/BuildingContractGrabber.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/Grabber/BuildingContractGrabber.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | ||||
| import { Grabber } from './Grabber'; | ||||
| import { grabActiveVillageId } from '../Page/VillageBlock'; | ||||
| import { getBuildingPageAttributes, isBuildingPage } from '../Page/PageDetectors'; | ||||
| import { grabContractResources, hasContractResources } from '../Page/BuildingPage/BuildingPage'; | ||||
| import { ContractType } from '../Scheduler'; | ||||
|  | ||||
| export class BuildingContractGrabber extends Grabber { | ||||
|     grab(): void { | ||||
|         if (!isBuildingPage()) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         const building = getBuildingPageAttributes(); | ||||
|         if (!building.buildTypeId) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (!hasContractResources()) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         const villageId = grabActiveVillageId(); | ||||
|         const contract = grabContractResources(); | ||||
|  | ||||
|         this.scheduler.updateResources(contract, { | ||||
|             type: ContractType.UpgradeBuilding, | ||||
|             villageId, | ||||
|             buildId: building.buildId, | ||||
|         }); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										26
									
								
								src/Grabber/ForgeContractGrabber.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/Grabber/ForgeContractGrabber.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| import { Grabber } from './Grabber'; | ||||
| import { grabActiveVillageId } from '../Page/VillageBlock'; | ||||
| import { getBuildingPageAttributes, isForgePage } from '../Page/PageDetectors'; | ||||
| import { ContractType } from '../Scheduler'; | ||||
| import { grabImprovementContracts } from '../Page/BuildingPage/ForgePage'; | ||||
|  | ||||
| export class ForgeContractGrabber extends Grabber { | ||||
|     grab(): void { | ||||
|         if (!isForgePage()) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         const villageId = grabActiveVillageId(); | ||||
|         const { buildId } = getBuildingPageAttributes(); | ||||
|         const contracts = grabImprovementContracts(); | ||||
|  | ||||
|         for (let { resources, unitId } of contracts) { | ||||
|             this.scheduler.updateResources(resources, { | ||||
|                 type: ContractType.ImproveTrooper, | ||||
|                 villageId, | ||||
|                 buildId, | ||||
|                 unitId, | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,3 +1,11 @@ | ||||
| import { Scheduler } from '../Scheduler'; | ||||
|  | ||||
| export abstract class Grabber { | ||||
|     protected scheduler: Scheduler; | ||||
|  | ||||
|     constructor(scheduler: Scheduler) { | ||||
|         this.scheduler = scheduler; | ||||
|     } | ||||
|  | ||||
|     abstract grab(): void; | ||||
| } | ||||
|   | ||||
| @@ -3,16 +3,21 @@ import { VillageResourceGrabber } from './VillageResourceGrabber'; | ||||
| import { VillageOverviewPageGrabber } from './VillageOverviewPageGrabber'; | ||||
| import { HeroPageGrabber } from './HeroPageGrabber'; | ||||
| import { MarketPageGrabber } from './MarketPageGrabber'; | ||||
| import { Scheduler } from '../Scheduler'; | ||||
| import { BuildingContractGrabber } from './BuildingContractGrabber'; | ||||
| import { ForgeContractGrabber } from './ForgeContractGrabber'; | ||||
|  | ||||
| export class GrabberManager { | ||||
|     private readonly grabbers: Array<Grabber> = []; | ||||
|  | ||||
|     constructor() { | ||||
|     constructor(scheduler: Scheduler) { | ||||
|         this.grabbers = []; | ||||
|         this.grabbers.push(new VillageResourceGrabber()); | ||||
|         this.grabbers.push(new VillageOverviewPageGrabber()); | ||||
|         this.grabbers.push(new HeroPageGrabber()); | ||||
|         this.grabbers.push(new MarketPageGrabber()); | ||||
|         this.grabbers.push(new VillageResourceGrabber(scheduler)); | ||||
|         this.grabbers.push(new VillageOverviewPageGrabber(scheduler)); | ||||
|         this.grabbers.push(new HeroPageGrabber(scheduler)); | ||||
|         this.grabbers.push(new MarketPageGrabber(scheduler)); | ||||
|         this.grabbers.push(new BuildingContractGrabber(scheduler)); | ||||
|         this.grabbers.push(new ForgeContractGrabber(scheduler)); | ||||
|     } | ||||
|  | ||||
|     grab() { | ||||
|   | ||||
| @@ -62,8 +62,16 @@ export function grabResourcesFromList($els: JQuery) { | ||||
|     return new Resources(grab(0), grab(1), grab(2), grab(3)); | ||||
| } | ||||
|  | ||||
| function findContractResourceElements() { | ||||
|     return jQuery('#contract .resource'); | ||||
| } | ||||
|  | ||||
| export function hasContractResources(): boolean { | ||||
|     return findContractResourceElements().length !== 0; | ||||
| } | ||||
|  | ||||
| export function grabContractResources(): Resources { | ||||
|     const $els = jQuery('#contract .resource'); | ||||
|     const $els = findContractResourceElements(); | ||||
|     if ($els.length === 0) { | ||||
|         throw new GrabError('No resource contract element'); | ||||
|     } | ||||
|   | ||||
| @@ -9,16 +9,15 @@ interface ResearchClickHandler { | ||||
|  | ||||
| export function createResearchButtons(onClickHandler: ResearchClickHandler) { | ||||
|     const $els = jQuery('.research'); | ||||
|     $els.each((index, $el) => createResearchButton(jQuery($el), onClickHandler)); | ||||
|     $els.each((index, el) => createResearchButton(jQuery(el), onClickHandler)); | ||||
| } | ||||
|  | ||||
| function createResearchButton($el: JQuery, onClickHandler: ResearchClickHandler) { | ||||
|     const unitId = grabUnitId($el); | ||||
|     const resElement = $el.find('.resourceWrapper .resource'); | ||||
|     const resources = grabResourcesFromList(resElement); | ||||
| function createResearchButton($researchBlockEl: JQuery, onClickHandler: ResearchClickHandler) { | ||||
|     const unitId = grabUnitId($researchBlockEl); | ||||
|     const resources = grabResources($researchBlockEl); | ||||
|  | ||||
|     const id = uniqId(); | ||||
|     $el.find('.cta').after(`<div style="padding: 8px"> | ||||
|     $researchBlockEl.find('.cta').after(`<div style="padding: 8px"> | ||||
|         <a id="${id}" href="#">Исследовать</a> | ||||
|     </div>`); | ||||
|  | ||||
| @@ -28,11 +27,16 @@ function createResearchButton($el: JQuery, onClickHandler: ResearchClickHandler) | ||||
|     }); | ||||
| } | ||||
|  | ||||
| function grabUnitId($el: JQuery) { | ||||
|     const unitImg = $el.find('img.unit'); | ||||
| function grabUnitId($researchBlockEl: JQuery) { | ||||
|     const unitImg = $researchBlockEl.find('img.unit'); | ||||
|     return getNumber(elClassId(unitImg.attr('class'), 'u')); | ||||
| } | ||||
|  | ||||
| function grabResources($researchBlockEl: JQuery) { | ||||
|     const $resEls = $researchBlockEl.find('.resourceWrapper .resource'); | ||||
|     return grabResourcesFromList($resEls); | ||||
| } | ||||
|  | ||||
| export function clickResearchButton(unitId: number) { | ||||
|     const $blockEl = findResearchBlockByUnitId(unitId); | ||||
|     if ($blockEl === undefined) { | ||||
| @@ -57,3 +61,20 @@ function findResearchBlockByUnitId(unitId: number): JQuery | undefined { | ||||
|     }); | ||||
|     return $blockEl; | ||||
| } | ||||
|  | ||||
| interface ImprovementContract { | ||||
|     unitId: number; | ||||
|     resources: Resources; | ||||
| } | ||||
|  | ||||
| export function grabImprovementContracts(): Array<ImprovementContract> { | ||||
|     const result: Array<ImprovementContract> = []; | ||||
|     const $els = jQuery('.research'); | ||||
|     $els.each((index, el) => { | ||||
|         const $researchBlockEl = jQuery(el); | ||||
|         const unitId = grabUnitId($researchBlockEl); | ||||
|         const resources = grabResources($researchBlockEl); | ||||
|         result.push({ unitId, resources }); | ||||
|     }); | ||||
|     return result; | ||||
| } | ||||
|   | ||||
| @@ -84,7 +84,6 @@ export class BuildingPageController { | ||||
|                 resources: resources.scale(chunk), | ||||
|                 trainCount: chunk, | ||||
|             }; | ||||
|             console.log('TRAIN TROOP', args); | ||||
|             this.scheduler.scheduleTask(TrainTroopTask.name, args); | ||||
|         } | ||||
|         notify(`Training ${count} troopers scheduled`); | ||||
|   | ||||
| @@ -2,11 +2,12 @@ import { elClassId, getNumber, parseLocation } from '../utils'; | ||||
| import { FORGE_ID, MARKET_ID } from '../Core/Buildings'; | ||||
|  | ||||
| export interface BuildingPageAttributes { | ||||
|     buildId: number; | ||||
|     buildTypeId: number; | ||||
|     categoryId: number; | ||||
|     sheetId: number; | ||||
|     tabId: number; | ||||
|     level: number; | ||||
|     buildId: number | undefined; | ||||
|     categoryId: number | undefined; | ||||
|     sheetId: number | undefined; | ||||
|     tabId: number | undefined; | ||||
| } | ||||
|  | ||||
| export function isBuildingPage() { | ||||
| @@ -24,12 +25,14 @@ export function getBuildingPageAttributes(): BuildingPageAttributes { | ||||
|         throw Error('Not building page'); | ||||
|     } | ||||
|     const p = parseLocation(); | ||||
|     const $buildEl = jQuery('#build'); | ||||
|     return { | ||||
|         buildId: getNumber(p.query.id), | ||||
|         buildTypeId: getNumber(elClassId(jQuery('#build').attr('class'), 'gid')), | ||||
|         buildTypeId: getNumber(elClassId($buildEl.attr('class'), 'gid')), | ||||
|         level: getNumber(elClassId($buildEl.attr('class'), 'level')), | ||||
|         buildId: getNumber(p.query.id) || undefined, | ||||
|         categoryId: getNumber(p.query.category, 1), | ||||
|         sheetId: getNumber(p.query.s, 0), | ||||
|         tabId: getNumber(p.query.t, 0), | ||||
|         sheetId: getNumber(p.query.s) || undefined, | ||||
|         tabId: getNumber(p.query.t) || undefined, | ||||
|     }; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -14,6 +14,18 @@ import { SendResourcesTask } from './Task/SendResourcesTask'; | ||||
| import { Args } from './Queue/Args'; | ||||
| import { ImmutableTaskList, Task, TaskId } from './Queue/TaskProvider'; | ||||
|  | ||||
| export enum ContractType { | ||||
|     UpgradeBuilding, | ||||
|     ImproveTrooper, | ||||
| } | ||||
|  | ||||
| interface ContractAttributes { | ||||
|     type: ContractType; | ||||
|     villageId?: number; | ||||
|     buildId?: number; | ||||
|     unitId?: number; | ||||
| } | ||||
|  | ||||
| export class Scheduler { | ||||
|     private taskQueue: TaskQueue; | ||||
|     private actionQueue: ActionQueue; | ||||
| @@ -100,11 +112,28 @@ export class Scheduler { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     updateResources(taskId: TaskId, resources: Resources): void { | ||||
|         this.taskQueue.modify( | ||||
|             t => t.id === taskId, | ||||
|             t => withResources(t, resources) | ||||
|         ); | ||||
|     updateResources(resources: Resources, attr: ContractAttributes): void { | ||||
|         if (attr.type === ContractType.UpgradeBuilding && attr.villageId && attr.buildId) { | ||||
|             this.taskQueue.modify( | ||||
|                 t => | ||||
|                     t.name === UpgradeBuildingTask.name && | ||||
|                     t.args.villageId === attr.villageId && | ||||
|                     t.args.buildId === attr.buildId, | ||||
|                 t => withResources(t, resources) | ||||
|             ); | ||||
|             this.logger.info('Update upgrade contracts', attr, resources); | ||||
|         } | ||||
|         if (attr.type === ContractType.ImproveTrooper && attr.villageId && attr.buildId && attr.unitId) { | ||||
|             this.taskQueue.modify( | ||||
|                 t => | ||||
|                     t.name === UpgradeBuildingTask.name && | ||||
|                     t.args.villageId === attr.villageId && | ||||
|                     t.args.buildId === attr.buildId && | ||||
|                     t.args.unitId === attr.unitId, | ||||
|                 t => withResources(t, resources) | ||||
|             ); | ||||
|             this.logger.info('Update improve contracts', attr, resources); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     scheduleActions(actions: Array<Action>): void { | ||||
|   | ||||
| @@ -1,36 +1,33 @@ | ||||
| import { TaskController, registerTask } from './TaskController'; | ||||
| import { TaskController, registerTask, ActionDefinition } from './TaskController'; | ||||
| import { GoToPageAction } from '../Action/GoToPageAction'; | ||||
| import { path } from '../utils'; | ||||
| import { UpgradeBuildingTask } from './UpgradeBuildingTask'; | ||||
| import { UpdateBuildingTaskResourcesAction } from '../Action/UpdateBuildingTaskResourcesAction'; | ||||
| import { CompleteTaskAction } from '../Action/CompleteTaskAction'; | ||||
| import { Action } from '../Queue/ActionQueue'; | ||||
| import { Args } from '../Queue/Args'; | ||||
| import { Task } from '../Queue/TaskProvider'; | ||||
| import { ImmutableTaskList, Task } from '../Queue/TaskProvider'; | ||||
| import { ForgeImprovementTask } from './ForgeImprovementTask'; | ||||
|  | ||||
| @registerTask | ||||
| export class UpdateResourceContracts extends TaskController { | ||||
|     async run(task: Task) { | ||||
|         const args: Args = { ...task.args, taskId: task.id }; | ||||
|  | ||||
|         const actions: Array<Action> = []; | ||||
|  | ||||
|     defineActions(task: Task): Array<ActionDefinition> { | ||||
|         const tasks = this.scheduler.getTaskItems(); | ||||
|         for (let task of tasks) { | ||||
|             const { villageId, buildId } = task.args; | ||||
|             if (task.name === UpgradeBuildingTask.name && villageId && buildId) { | ||||
|                 actions.push( | ||||
|                     new Action(GoToPageAction.name, { | ||||
|                         ...args, | ||||
|                         path: path('/build.php', { newdid: villageId, id: buildId }), | ||||
|                     }) | ||||
|                 ); | ||||
|                 actions.push(new Action(UpdateBuildingTaskResourcesAction.name, { ...args, targetTaskId: task.id })); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         actions.push(new Action(CompleteTaskAction.name, args)); | ||||
|         return [...this.walkUpgradeTasks(tasks), ...this.walkImprovementTask(tasks)]; | ||||
|     } | ||||
|  | ||||
|         this.scheduler.scheduleActions(actions); | ||||
|     private walkUpgradeTasks(tasks: ImmutableTaskList): Array<ActionDefinition> { | ||||
|         return tasks | ||||
|             .filter(t => t.name === UpgradeBuildingTask.name && t.args.villageId && t.args.buildId) | ||||
|             .map(t => [ | ||||
|                 GoToPageAction.name, | ||||
|                 { path: path('/build.php', { newdid: t.args.villageId, id: t.args.buildId }) }, | ||||
|             ]); | ||||
|     } | ||||
|  | ||||
|     private walkImprovementTask(tasks: ImmutableTaskList): Array<ActionDefinition> { | ||||
|         return tasks | ||||
|             .filter(t => t.name === ForgeImprovementTask.name && t.args.villageId && t.args.buildId) | ||||
|             .map(t => [ | ||||
|                 GoToPageAction.name, | ||||
|                 { path: path('/build.php', { newdid: t.args.villageId, id: t.args.buildId }) }, | ||||
|             ]); | ||||
|     } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user