diff --git a/src/Dashboard/Dashboard.ts b/src/Dashboard/Dashboard.ts index c3d9ddf..833cf75 100644 --- a/src/Dashboard/Dashboard.ts +++ b/src/Dashboard/Dashboard.ts @@ -1,9 +1,10 @@ import * as URLParse from 'url-parse'; -import { elClassId, markPage, waitForLoad } from '../utils'; +import { markPage, waitForLoad } from '../utils'; import { Scheduler } from '../Scheduler'; -import { UpgradeBuildingTask } from '../Task/UpgradeBuildingTask'; import { TaskQueueRenderer } from '../TaskQueueRenderer'; -import { BuildPage } from './BuildPage'; +import { BuildPage } from '../Page/BuildPage'; +import { grabActiveVillageId, showBuildingSlotIds, showFieldsSlotIds } from '../Page/EveryPage'; +import { UpgradeBuildingTask } from '../Task/UpgradeBuildingTask'; export class Dashboard { private readonly version: string; @@ -24,12 +25,19 @@ export class Dashboard { this.renderTaskQueue(); setInterval(() => this.renderTaskQueue(), 5000); + const villageId = grabActiveVillageId(); + + const tasks = this.scheduler.getTaskItems(); + const buildingsInQueue = tasks + .filter(t => t.name === UpgradeBuildingTask.name && t.args.villageId === villageId) + .map(t => t.args.buildId); + if (p.pathname === '/dorf1.php') { - this.showSlotIds('buildingSlot'); + showFieldsSlotIds(buildingsInQueue); } if (p.pathname === '/dorf2.php') { - this.showSlotIds('aid'); + showBuildingSlotIds(buildingsInQueue); } if (p.pathname === '/build.php') { @@ -42,27 +50,6 @@ export class Dashboard { new TaskQueueRenderer().render(this.scheduler.getTaskItems()); } - private showSlotIds(prefix: string) { - const tasks = this.scheduler.getTaskItems(); - jQuery('.level.colorLayer').each((idx, el) => { - const buildId = elClassId(jQuery(el).attr('class') || '', prefix); - const oldLabel = jQuery(el) - .find('.labelLayer') - .text(); - jQuery(el) - .find('.labelLayer') - .text(buildId + ':' + oldLabel); - const inQueue = tasks.find( - t => t.cmd.name === UpgradeBuildingTask.name && Number(t.cmd.args.id) === Number(buildId) - ); - if (inQueue !== undefined) { - jQuery(el).css({ - 'background-image': 'linear-gradient(to top, #f00, #f00 100%)', - }); - } - }); - } - private log(...args) { console.log('SCHEDULER:', ...args); } diff --git a/src/Dashboard/BuildPage.ts b/src/Page/BuildPage.ts similarity index 82% rename from src/Dashboard/BuildPage.ts rename to src/Page/BuildPage.ts index 5891bb9..728b5e1 100644 --- a/src/Dashboard/BuildPage.ts +++ b/src/Page/BuildPage.ts @@ -1,8 +1,8 @@ import { elClassId, split, uniqId } from '../utils'; -import { Command } from '../Common'; import { UpgradeBuildingTask } from '../Task/UpgradeBuildingTask'; import { Scheduler } from '../Scheduler'; import { TrainTroopTask } from '../Task/TrainTroopTask'; +import { grabActiveVillageId } from './EveryPage'; const QUARTERS_ID = 19; @@ -34,12 +34,10 @@ export class BuildPage { }); } - private onScheduleBuilding(id: number) { - const queueItem = new Command(UpgradeBuildingTask.name, { - id, - }); - this.scheduler.scheduleTask(queueItem); - const n = new Notification(`Building ${id} scheduled`); + private onScheduleBuilding(buildId: number) { + const villageId = grabActiveVillageId(); + this.scheduler.scheduleTask(UpgradeBuildingTask.name, { villageId, buildId }); + const n = new Notification(`Building ${buildId} scheduled`); setTimeout(() => n && n.close(), 4000); } @@ -63,18 +61,18 @@ export class BuildPage { private onTrainTroopClick(buildId: Number, troopId: Number, el: HTMLElement) { console.log('TRAIN TROOPERS', 'TROOP ID', troopId, 'BUILDING ID', buildId); + const villageId = grabActiveVillageId(); const input = jQuery(el).find(`input[name="t${troopId}"]`); const count = Number(input.val()); if (!isNaN(count) && count > 0) { console.log('PREPARE TO TRAIN', count, 'TROOPERS'); for (let n of split(count)) { - this.scheduler.scheduleTask( - new Command(TrainTroopTask.name, { - buildId, - troopId, - trainCount: n, - }) - ); + this.scheduler.scheduleTask(TrainTroopTask.name, { + villageId, + buildId, + troopId, + trainCount: n, + }); } } } diff --git a/src/Page/EveryPage.ts b/src/Page/EveryPage.ts new file mode 100644 index 0000000..0f435f5 --- /dev/null +++ b/src/Page/EveryPage.ts @@ -0,0 +1,35 @@ +import * as URLParse from 'url-parse'; +import { elClassId, getNumber } from '../utils'; + +export function grabActiveVillageId(): number { + const href = jQuery('#sidebarBoxVillagelist a.active').attr('href'); + const p = new URLParse(href || '', true); + console.log('VILLAGE REF', href, p); + return getNumber(p.query.newdid); +} + +function showSlotIds(prefix: string, buildingIds: number[]): void { + jQuery('.level.colorLayer').each((idx, el) => { + const buildId = getNumber(elClassId(jQuery(el).attr('class') || '', prefix)); + const oldLabel = jQuery(el) + .find('.labelLayer') + .text(); + jQuery(el) + .find('.labelLayer') + .text(buildId + ':' + oldLabel); + const inQueue = buildingIds.includes(buildId); + if (inQueue) { + jQuery(el).css({ + 'background-image': 'linear-gradient(to top, #f00, #f00 100%)', + }); + } + }); +} + +export function showFieldsSlotIds(buildingIds: number[]) { + showSlotIds('buildingSlot', buildingIds); +} + +export function showBuildingSlotIds(buildingIds: number[]) { + showSlotIds('aid', buildingIds); +} diff --git a/src/Scheduler.ts b/src/Scheduler.ts index 7096278..3fc1388 100644 --- a/src/Scheduler.ts +++ b/src/Scheduler.ts @@ -47,7 +47,7 @@ export class Scheduler { private scheduleUniqTask(seconds: number, name: string, args: Args = {}) { const taskScheduler = () => { if (!this.taskQueue.hasNamed(name)) { - this.taskQueue.push(new Command(name, args), timestamp() + 10 * 60); + this.taskQueue.push(name, args, timestamp() + 10 * 60); } }; taskScheduler(); @@ -95,12 +95,12 @@ export class Scheduler { } private async processTaskCommand(task: Task) { - const taskController = createTask(task.cmd.name, this); - this.log('PROCESS TASK', task.cmd.name, task, taskController); + const taskController = createTask(task.name, this); + this.log('PROCESS TASK', task.name, task, taskController); if (taskController) { await taskController.run(task); } else { - this.logWarn('TASK NOT FOUND', task.cmd.name); + this.logWarn('TASK NOT FOUND', task.name); this.taskQueue.complete(task.id); } } @@ -123,7 +123,7 @@ export class Scheduler { if (err instanceof BuildingQueueFullError) { this.logWarn('BUILDING QUEUE FULL, TRY ALL AFTER', err.seconds); this.taskQueue.modify( - t => t.cmd.name === UpgradeBuildingTask.name, + t => t.name === UpgradeBuildingTask.name, t => t.withTime(timestamp() + err.seconds) ); return; @@ -146,9 +146,9 @@ export class Scheduler { this.taskQueue.complete(id); } - scheduleTask(task: Command): void { - this.log('PUSH TASK', task); - this.taskQueue.push(task, timestamp()); + scheduleTask(name: string, args: Args): void { + this.log('PUSH TASK', name, args); + this.taskQueue.push(name, args, timestamp()); } scheduleActions(actions: Array): void { diff --git a/src/Storage/TaskQueue.ts b/src/Storage/TaskQueue.ts index 5d77333..439fe2f 100644 --- a/src/Storage/TaskQueue.ts +++ b/src/Storage/TaskQueue.ts @@ -1,7 +1,7 @@ -import { Command } from '../Common'; +import { Args } from '../Common'; import { uniqId } from '../utils'; -const QUEUE_NAME = 'task_queue:v3'; +const QUEUE_NAME = 'task_queue:v4'; export type TaskId = string; @@ -12,25 +12,27 @@ function uniqTaskId(): TaskId { export class Task { readonly id: TaskId; readonly ts: number; - readonly cmd: Command; - constructor(id: TaskId, ts: number, cmd: Command) { + readonly name: string; + readonly args: Args; + constructor(id: TaskId, ts: number, name: string, args: Args) { this.id = id; this.ts = ts; - this.cmd = cmd; + this.name = name; + this.args = args; } withTime(ts: number): Task { - return new Task(this.id, ts, this.cmd); + return new Task(this.id, ts, this.name, this.args); } } export type TaskList = Array; export class TaskQueue { - push(cmd: Command, ts: number): Task { + push(name: string, args: Args, ts: number): Task { const id = uniqTaskId(); - const task = new Task(id, ts, cmd); - this.log('PUSH TASK', id, ts, cmd); + const task = new Task(id, ts, name, args); + this.log('PUSH TASK', id, ts, name, args); let items = this.getItems(); items.push(task); this.flushItems(items); @@ -51,7 +53,7 @@ export class TaskQueue { } hasNamed(name: string): boolean { - return this.has(t => t.cmd.name === name); + return this.has(t => t.name === name); } modify(predicate: (t: Task) => boolean, modifier: (t: Task) => Task) { @@ -101,7 +103,7 @@ export class TaskQueue { const storedItems = serialized !== null ? (JSON.parse(serialized) as Array<{ [key: string]: any }>) : []; const items: TaskList = []; storedItems.forEach(obj => { - items.push(new Task(obj.id || uniqId(), +obj.ts, obj.cmd)); + items.push(new Task(obj.id || uniqId(), +obj.ts, obj.name, obj.args)); }); return items; } diff --git a/src/Task/BalanceHeroResourcesTask.ts b/src/Task/BalanceHeroResourcesTask.ts index a82a746..b4cac86 100644 --- a/src/Task/BalanceHeroResourcesTask.ts +++ b/src/Task/BalanceHeroResourcesTask.ts @@ -3,18 +3,24 @@ 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'; +import { path } from '../utils'; @registerTask export class BalanceHeroResourcesTask extends TaskController { async run(task: Task) { - const args: Args = { ...task.cmd.args, taskId: task.id }; + const args: Args = { ...task.args, taskId: task.id }; this.scheduler.scheduleActions([ - new Command(GoToPageAction.name, { ...args, path: '/dorf1.php' }), + new Command(GoToPageAction.name, { + ...args, + path: path('/dorf1.php'), + }), new Command(GrabVillageResourcesAction.name, args), - new Command(GoToPageAction.name, { ...args, path: 'hero.php' }), + new Command(GoToPageAction.name, { + ...args, + path: path('/hero.php'), + }), new Command(BalanceHeroResourcesAction.name, args), new Command(CompleteTaskAction.name, args), ]); diff --git a/src/Task/SendOnAdventureTask.ts b/src/Task/SendOnAdventureTask.ts index 87e132a..4f808e0 100644 --- a/src/Task/SendOnAdventureTask.ts +++ b/src/Task/SendOnAdventureTask.ts @@ -6,17 +6,21 @@ import { GrabHeroAttributesAction } from '../Action/GrabHeroAttributesAction'; import { CompleteTaskAction } from '../Action/CompleteTaskAction'; import { SendOnAdventureAction } from '../Action/SendOnAdventureAction'; import { ClickButtonAction } from '../Action/ClickButtonAction'; +import { path } from '../utils'; @registerTask export class SendOnAdventureTask extends TaskController { async run(task: Task) { - const args: Args = { ...task.cmd.args, taskId: task.id }; + const args: Args = { ...task.args, taskId: task.id }; this.scheduler.scheduleActions([ - new Command(GoToPageAction.name, { ...args, path: 'hero.php' }), + new Command(GoToPageAction.name, { + ...args, + path: path('/hero.php'), + }), new Command(GrabHeroAttributesAction.name, args), new Command(GoToPageAction.name, { ...args, - path: '/hero.php?t=3', + path: path('/hero.php', { t: 3 }), }), new Command(SendOnAdventureAction.name, args), new Command(ClickButtonAction.name, { diff --git a/src/Task/TrainTroopTask.ts b/src/Task/TrainTroopTask.ts index 50d12e5..e937559 100644 --- a/src/Task/TrainTroopTask.ts +++ b/src/Task/TrainTroopTask.ts @@ -4,13 +4,17 @@ import { TaskController, registerTask } from './TaskController'; import { GoToPageAction } from '../Action/GoToPageAction'; import { CompleteTaskAction } from '../Action/CompleteTaskAction'; import { TrainTrooperAction } from '../Action/TrainTrooperAction'; +import { path } from '../utils'; @registerTask export class TrainTroopTask extends TaskController { async run(task: Task) { - const args: Args = { ...task.cmd.args, taskId: task.id }; + const args: Args = { ...task.args, taskId: task.id }; this.scheduler.scheduleActions([ - new Command(GoToPageAction.name, { ...args, path: '/build.php?id=' + args.buildId }), + new Command(GoToPageAction.name, { + ...args, + path: path('/build.php', { newdid: args.villageId, id: args.buildId }), + }), new Command(TrainTrooperAction.name, args), new Command(CompleteTaskAction.name, args), ]); diff --git a/src/Task/UpgradeBuildingTask.ts b/src/Task/UpgradeBuildingTask.ts index b38e1c0..0dc4a2b 100644 --- a/src/Task/UpgradeBuildingTask.ts +++ b/src/Task/UpgradeBuildingTask.ts @@ -5,17 +5,21 @@ import { TaskController, registerTask } from './TaskController'; import { GoToPageAction } from '../Action/GoToPageAction'; import { CheckBuildingRemainingTimeAction } from '../Action/CheckBuildingRemainingTimeAction'; import { CompleteTaskAction } from '../Action/CompleteTaskAction'; +import { path } from '../utils'; @registerTask export class UpgradeBuildingTask extends TaskController { async run(task: Task) { - const args: Args = { ...task.cmd.args, taskId: task.id }; + const args: Args = { ...task.args, taskId: task.id }; this.scheduler.scheduleActions([ - new Command(GoToPageAction.name, { ...args, path: '/dorf1.php' }), + new Command(GoToPageAction.name, { + ...args, + path: path('/dorf1.php', { newdid: args.villageId }), + }), new Command(CheckBuildingRemainingTimeAction.name, args), new Command(GoToPageAction.name, { ...args, - path: '/build.php?id=' + args.id, + path: path('/build.php', { newdid: args.villageId, id: args.buildId }), }), new Command(UpgradeBuildingAction.name, args), new Command(CompleteTaskAction.name, args), diff --git a/src/TaskQueueRenderer.ts b/src/TaskQueueRenderer.ts index a94e69e..bc0f1a1 100644 --- a/src/TaskQueueRenderer.ts +++ b/src/TaskQueueRenderer.ts @@ -25,7 +25,7 @@ export class TaskQueueRenderer { tasks.forEach(task => { ul.append( jQuery('
  • ').text( - formatDate(task.ts) + ' ' + task.cmd.name + ' ' + JSON.stringify(task.cmd.args) + ' ' + task.id + formatDate(task.ts) + ' ' + task.name + ' ' + JSON.stringify(task.args) + ' ' + task.id ) ); }); diff --git a/src/utils.ts b/src/utils.ts index 97f7a6f..e8cdcfa 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -71,6 +71,14 @@ export function getNumber(value: any, def: number = 0): number { return converted === undefined ? def : converted; } +export function path(p: string, query: { [key: string]: string | number } = {}) { + let parts: string[] = []; + for (let k in query) { + parts.push(`${k}=${query[k]}`); + } + return p + (parts.length ? '?' + parts.join('&') : ''); +} + export function markPage(text: string, version: string) { jQuery('body').append( '