From 9fdc57374608adffa867c3fa6d5255bed65688eb Mon Sep 17 00:00:00 2001 From: Anton Vakhrushev Date: Sun, 12 Apr 2020 20:41:26 +0300 Subject: [PATCH] Add build building task --- src/Action/BuildBuildingAction.ts | 24 +++++++++++++++++++ src/Common.ts | 2 ++ src/Dashboard/Dashboard.ts | 4 ++-- src/Page/BuildPage.ts | 35 ++++++++++++++++------------ src/Page/BuildingPage.ts | 38 +++++++++++++++++++++++++++++++ src/Page/VillageBlock.ts | 16 ++++++------- src/Task/BuildBuildingTask.ts | 28 +++++++++++++++++++++++ src/utils.ts | 5 ++++ 8 files changed, 127 insertions(+), 25 deletions(-) create mode 100644 src/Action/BuildBuildingAction.ts create mode 100644 src/Task/BuildBuildingTask.ts diff --git a/src/Action/BuildBuildingAction.ts b/src/Action/BuildBuildingAction.ts new file mode 100644 index 0000000..d559b42 --- /dev/null +++ b/src/Action/BuildBuildingAction.ts @@ -0,0 +1,24 @@ +import { ActionController, registerAction } from './ActionController'; +import { Args } from '../Common'; +import { ActionError, GrabError, TryLaterError } from '../Errors'; +import { Task } from '../Storage/TaskQueue'; +import { clickBuildButton } from '../Page/BuildingPage'; + +@registerAction +export class BuildBuildingAction extends ActionController { + async run(args: Args, task: Task): Promise { + const buildTypeId = args.buildTypeId; + if (!buildTypeId) { + throw new ActionError(task.id, 'Unknown build type id'); + } + + try { + clickBuildButton(buildTypeId); + } catch (e) { + if (e instanceof GrabError) { + throw new TryLaterError(task.id, 15 * 60, 'No build button, try later'); + } + throw e; + } + } +} diff --git a/src/Common.ts b/src/Common.ts index 396cce0..cdd8e7e 100644 --- a/src/Common.ts +++ b/src/Common.ts @@ -1,6 +1,8 @@ export interface Args { villageId?: number; buildId?: number; + categoryId?: number; + buildTypeId?: number; [name: string]: any; } diff --git a/src/Dashboard/Dashboard.ts b/src/Dashboard/Dashboard.ts index e2630bd..0a63fdd 100644 --- a/src/Dashboard/Dashboard.ts +++ b/src/Dashboard/Dashboard.ts @@ -1,5 +1,5 @@ import * as URLParse from 'url-parse'; -import { uniqId, waitForLoad } from '../utils'; +import { getNumber, toNumber, uniqId, waitForLoad } from '../utils'; import { Scheduler } from '../Scheduler'; import { BuildPage } from '../Page/BuildPage'; import { UpgradeBuildingTask } from '../Task/UpgradeBuildingTask'; @@ -77,7 +77,7 @@ export class Dashboard { } if (p.pathname === '/build.php') { - new BuildPage(this.scheduler, Number(p.query.id)).run(); + new BuildPage(this.scheduler, getNumber(p.query.id), getNumber(p.query.category, 1)).run(); } this.createControlPanel(state); diff --git a/src/Page/BuildPage.ts b/src/Page/BuildPage.ts index 8d34dbd..7c6f329 100644 --- a/src/Page/BuildPage.ts +++ b/src/Page/BuildPage.ts @@ -1,9 +1,11 @@ -import { elClassId, split, uniqId } from '../utils'; +import { elClassId, notify, split, uniqId } from '../utils'; import { UpgradeBuildingTask } from '../Task/UpgradeBuildingTask'; import { Scheduler } from '../Scheduler'; import { TrainTroopTask } from '../Task/TrainTroopTask'; import { grabActiveVillageId } from './VillageBlock'; import { Logger } from '../Logger'; +import { createBuildButton, createUpgradeButton } from './BuildingPage'; +import { BuildBuildingTask } from '../Task/BuildBuildingTask'; const QUARTERS_ID = 19; @@ -11,37 +13,40 @@ export class BuildPage { private scheduler: Scheduler; private readonly buildId: number; private readonly logger; - constructor(scheduler: Scheduler, buildId: number) { + private readonly categoryId: number; + + constructor(scheduler: Scheduler, buildId: number, categoryId: number) { this.scheduler = scheduler; this.buildId = buildId; + this.categoryId = categoryId; this.logger = new Logger(this.constructor.name); } run() { const buildTypeId = elClassId(jQuery('#build').attr('class') || '', 'gid'); this.logger.log('BUILD PAGE DETECTED', 'ID', this.buildId, 'TYPE', buildTypeId); - this.createUpgradeButton(); + + createBuildButton(buildTypeId => this.onScheduleBuildBuilding(buildTypeId)); + createUpgradeButton(() => this.onScheduleUpgradeBuilding()); + if (buildTypeId === QUARTERS_ID) { this.createTrainTroopButton(); } } - private createUpgradeButton() { - const id = uniqId(); - jQuery('.upgradeButtonsContainer .section1').append( - `
В очередь
` - ); - jQuery(`#${id}`).on('click', evt => { - evt.preventDefault(); - this.onScheduleBuilding(this.buildId); - }); + private onScheduleBuildBuilding(buildTypeId: number) { + const buildId = this.buildId; + const categoryId = this.categoryId; + const villageId = grabActiveVillageId(); + this.scheduler.scheduleTask(BuildBuildingTask.name, { villageId, buildId, categoryId, buildTypeId }); + notify(`Building ${buildId} scheduled`); } - private onScheduleBuilding(buildId: number) { + private onScheduleUpgradeBuilding() { + const buildId = this.buildId; const villageId = grabActiveVillageId(); this.scheduler.scheduleTask(UpgradeBuildingTask.name, { villageId, buildId }); - const n = new Notification(`Building ${buildId} scheduled`); - setTimeout(() => n && n.close(), 4000); + notify(`Upgrading ${buildId} scheduled`); } private createTrainTroopButton() { diff --git a/src/Page/BuildingPage.ts b/src/Page/BuildingPage.ts index aee2aef..5a48149 100644 --- a/src/Page/BuildingPage.ts +++ b/src/Page/BuildingPage.ts @@ -1,4 +1,31 @@ import { GrabError } from '../Errors'; +import { getNumber, trimPrefix, uniqId } from '../utils'; + +export function clickBuildButton(typeId: number) { + const section = jQuery(`#contract_building${typeId}`); + if (section.length !== 1) { + throw new GrabError('No build section'); + } + const btn = section.find('.contractLink button.green.new'); + if (btn.length !== 1) { + throw new GrabError('No build button, try later'); + } + btn.trigger('click'); +} + +export function createBuildButton(onClickHandler: (buildTypeId: number) => void) { + const $els = jQuery('[id^=contract_building]'); + $els.each((idx, el) => { + const $el = jQuery(el); + const id = getNumber(trimPrefix($el.attr('id') || '', 'contract_building')); + const btnId = uniqId(); + $el.append(`
Построить
`); + jQuery(`#${btnId}`).on('click', evt => { + evt.preventDefault(); + onClickHandler(id); + }); + }); +} export function clickUpgradeButton() { const btn = jQuery('.upgradeButtonsContainer .section1 button.green.build'); @@ -7,3 +34,14 @@ export function clickUpgradeButton() { } btn.trigger('click'); } + +export function createUpgradeButton(onClickHandler: () => void) { + const id = uniqId(); + jQuery('.upgradeButtonsContainer .section1').append( + `
В очередь
` + ); + jQuery(`#${id}`).on('click', evt => { + evt.preventDefault(); + onClickHandler(); + }); +} diff --git a/src/Page/VillageBlock.ts b/src/Page/VillageBlock.ts index fce79e0..0f4be6b 100644 --- a/src/Page/VillageBlock.ts +++ b/src/Page/VillageBlock.ts @@ -3,6 +3,14 @@ import { GrabError } from '../Errors'; import * as URLParse from 'url-parse'; import { getNumber } from '../utils'; +function getVillageListItems() { + const $elements = jQuery('#sidebarBoxVillagelist ul li a'); + if ($elements.length === 0) { + throw new GrabError('Village list items not found'); + } + return $elements; +} + export function grabVillageList(): VillageList { const villageList: VillageList = []; const $elements = getVillageListItems(); @@ -26,14 +34,6 @@ export function grabActiveVillageId(): number { return grabActiveVillage()?.id || 0; } -function getVillageListItems() { - const $elements = jQuery('#sidebarBoxVillagelist ul li a'); - if ($elements.length === 0) { - throw new GrabError('Village list items not found'); - } - return $elements; -} - function grabVillageInfo($el): Village { const href = $el.attr('href'); const parsedHref = new URLParse(href || '', true); diff --git a/src/Task/BuildBuildingTask.ts b/src/Task/BuildBuildingTask.ts new file mode 100644 index 0000000..46ad720 --- /dev/null +++ b/src/Task/BuildBuildingTask.ts @@ -0,0 +1,28 @@ +import { Args, Command } from '../Common'; +import { BuildBuildingAction } from '../Action/BuildBuildingAction'; +import { CheckBuildingRemainingTimeAction } from '../Action/CheckBuildingRemainingTimeAction'; +import { CompleteTaskAction } from '../Action/CompleteTaskAction'; +import { GoToPageAction } from '../Action/GoToPageAction'; +import { path } from '../utils'; +import { Task } from '../Storage/TaskQueue'; +import { TaskController, registerTask } from './TaskController'; + +@registerTask +export class BuildBuildingTask extends TaskController { + async run(task: Task) { + const args: Args = { ...task.args, taskId: task.id }; + this.scheduler.scheduleActions([ + new Command(GoToPageAction.name, { + ...args, + path: path('/dorf1.php', { newdid: args.villageId }), + }), + new Command(CheckBuildingRemainingTimeAction.name, args), + new Command(GoToPageAction.name, { + ...args, + path: path('/build.php', { newdid: args.villageId, id: args.buildId, category: args.categoryId }), + }), + new Command(BuildBuildingAction.name, args), + new Command(CompleteTaskAction.name, args), + ]); + } +} diff --git a/src/utils.ts b/src/utils.ts index 339f80c..a4ca548 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -95,6 +95,11 @@ export function path(p: string, query: { [key: string]: string | number | undefi return p + (parts.length ? '?' + parts.join('&') : ''); } +export function notify(msg: string): void { + const n = new Notification(msg); + setTimeout(() => n && n.close(), 4000); +} + export function markPage(text: string, version: string) { jQuery('body').append( '