diff --git a/src/Action/UpdateBuildingTaskResourcesAction.ts b/src/Action/UpdateBuildingTaskResourcesAction.ts deleted file mode 100644 index 8dc3b4e..0000000 --- a/src/Action/UpdateBuildingTaskResourcesAction.ts +++ /dev/null @@ -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 { - const buildingTaskId = args.targetTaskId; - if (buildingTaskId === undefined) { - return; - } - - try { - const resources = grabContractResources(); - this.scheduler.updateResources(buildingTaskId, resources); - } catch (e) { - return; - } - } -} diff --git a/src/Executor.ts b/src/Executor.ts index 100d364..65ea3ea 100644 --- a/src/Executor.ts +++ b/src/Executor.ts @@ -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); diff --git a/src/Grabber/BuildingContractGrabber.ts b/src/Grabber/BuildingContractGrabber.ts new file mode 100644 index 0000000..1ef1bab --- /dev/null +++ b/src/Grabber/BuildingContractGrabber.ts @@ -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, + }); + } +} diff --git a/src/Grabber/ForgeContractGrabber.ts b/src/Grabber/ForgeContractGrabber.ts new file mode 100644 index 0000000..9a786ce --- /dev/null +++ b/src/Grabber/ForgeContractGrabber.ts @@ -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, + }); + } + } +} diff --git a/src/Grabber/Grabber.ts b/src/Grabber/Grabber.ts index 8c3b9ec..269be09 100644 --- a/src/Grabber/Grabber.ts +++ b/src/Grabber/Grabber.ts @@ -1,3 +1,11 @@ +import { Scheduler } from '../Scheduler'; + export abstract class Grabber { + protected scheduler: Scheduler; + + constructor(scheduler: Scheduler) { + this.scheduler = scheduler; + } + abstract grab(): void; } diff --git a/src/Grabber/GrabberManager.ts b/src/Grabber/GrabberManager.ts index dbaceb3..9a00a34 100644 --- a/src/Grabber/GrabberManager.ts +++ b/src/Grabber/GrabberManager.ts @@ -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 = []; - 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() { diff --git a/src/Page/BuildingPage/BuildingPage.ts b/src/Page/BuildingPage/BuildingPage.ts index bc34ee5..aed7863 100644 --- a/src/Page/BuildingPage/BuildingPage.ts +++ b/src/Page/BuildingPage/BuildingPage.ts @@ -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'); } diff --git a/src/Page/BuildingPage/ForgePage.ts b/src/Page/BuildingPage/ForgePage.ts index 9b2cd9c..015d661 100644 --- a/src/Page/BuildingPage/ForgePage.ts +++ b/src/Page/BuildingPage/ForgePage.ts @@ -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(`
+ $researchBlockEl.find('.cta').after(`
Исследовать
`); @@ -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 { + const result: Array = []; + 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; +} diff --git a/src/Page/BuildingPageController.ts b/src/Page/BuildingPageController.ts index 4733cdd..3b29e48 100644 --- a/src/Page/BuildingPageController.ts +++ b/src/Page/BuildingPageController.ts @@ -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`); diff --git a/src/Page/PageDetectors.ts b/src/Page/PageDetectors.ts index 6cbc044..36ad4be 100644 --- a/src/Page/PageDetectors.ts +++ b/src/Page/PageDetectors.ts @@ -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, }; } diff --git a/src/Scheduler.ts b/src/Scheduler.ts index 1809046..44978d4 100644 --- a/src/Scheduler.ts +++ b/src/Scheduler.ts @@ -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): void { diff --git a/src/Task/UpdateResourceContracts.ts b/src/Task/UpdateResourceContracts.ts index f684c23..1c2e448 100644 --- a/src/Task/UpdateResourceContracts.ts +++ b/src/Task/UpdateResourceContracts.ts @@ -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 = []; - + defineActions(task: Task): Array { 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 { + 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 { + 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 }) }, + ]); } }