Automatic action resolving with decorators and magic
This commit is contained in:
parent
54fca1f4f4
commit
29485d233d
@ -1,6 +1,35 @@
|
||||
import { Args } from '../Common';
|
||||
import { Task } from '../Storage/TaskQueue';
|
||||
import { GameState } from '../Storage/GameState';
|
||||
import Scheduler from '../Scheduler';
|
||||
|
||||
export default abstract class ActionController {
|
||||
abstract async run(args: Args, task: Task);
|
||||
const actionMap: { [name: string]: Function | undefined } = {};
|
||||
|
||||
export function registerAction(constructor: Function) {
|
||||
console.log('REGISTER ACTION', constructor.name);
|
||||
actionMap[constructor.name] = constructor;
|
||||
}
|
||||
|
||||
export function createAction(
|
||||
name: string,
|
||||
state: GameState,
|
||||
scheduler: Scheduler
|
||||
): ActionController | undefined {
|
||||
const storedFunction = actionMap[name];
|
||||
if (storedFunction === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
const constructor = (storedFunction as unknown) as typeof ActionController;
|
||||
return new constructor(state, scheduler);
|
||||
}
|
||||
|
||||
export class ActionController {
|
||||
protected state: GameState;
|
||||
protected scheduler: Scheduler;
|
||||
constructor(state: GameState, scheduler: Scheduler) {
|
||||
this.state = state;
|
||||
this.scheduler = scheduler;
|
||||
}
|
||||
|
||||
async run(args: Args, task: Task) {}
|
||||
}
|
||||
|
@ -1,11 +1,10 @@
|
||||
import ActionController from './ActionController';
|
||||
import { ActionController, registerAction } from './ActionController';
|
||||
import { Args } from '../Common';
|
||||
import { Task } from '../Storage/TaskQueue';
|
||||
import { BuildingQueueFullError } from '../Errors';
|
||||
|
||||
export default class CheckBuildingRemainingTimeAction extends ActionController {
|
||||
static NAME = 'check_building_remaining_time';
|
||||
|
||||
@registerAction
|
||||
export class CheckBuildingRemainingTimeAction extends ActionController {
|
||||
async run(args: Args, task: Task): Promise<any> {
|
||||
const timer = jQuery('.buildDuration .timer');
|
||||
if (timer.length === 1) {
|
||||
|
@ -1,9 +1,9 @@
|
||||
import ActionController from './ActionController';
|
||||
import { ActionController, registerAction } from './ActionController';
|
||||
import { Args } from '../Common';
|
||||
import { Task } from '../Storage/TaskQueue';
|
||||
|
||||
export default class ClickButtonAction extends ActionController {
|
||||
static NAME = 'click_button';
|
||||
@registerAction
|
||||
export class ClickButtonAction extends ActionController {
|
||||
async run(args: Args, task: Task): Promise<any> {
|
||||
const el = jQuery(args.selector);
|
||||
if (el.length === 1) {
|
||||
|
@ -1,16 +1,9 @@
|
||||
import ActionController from './ActionController';
|
||||
import { ActionController, registerAction } from './ActionController';
|
||||
import { Args } from '../Common';
|
||||
import { Task } from '../Storage/TaskQueue';
|
||||
import Scheduler from '../Scheduler';
|
||||
|
||||
export default class CompleteTaskAction extends ActionController {
|
||||
static NAME = 'complete_task';
|
||||
private scheduler: Scheduler;
|
||||
|
||||
constructor(scheduler: Scheduler) {
|
||||
super();
|
||||
this.scheduler = scheduler;
|
||||
}
|
||||
@registerAction
|
||||
export class CompleteTaskAction extends ActionController {
|
||||
async run(args: Args, task: Task): Promise<any> {
|
||||
this.scheduler.completeTask(task.id);
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
import ActionController from './ActionController';
|
||||
import { ActionController, registerAction } from './ActionController';
|
||||
import { Args } from '../Common';
|
||||
import { Task } from '../Storage/TaskQueue';
|
||||
|
||||
export default class GoToPageAction extends ActionController {
|
||||
static NAME = 'go_to_page';
|
||||
@registerAction
|
||||
export class GoToPageAction extends ActionController {
|
||||
async run(args: Args, task: Task): Promise<any> {
|
||||
window.location.assign(args.path);
|
||||
}
|
||||
|
@ -1,18 +1,10 @@
|
||||
import ActionController from './ActionController';
|
||||
import { ActionController, registerAction } from './ActionController';
|
||||
import { Args } from '../Common';
|
||||
import { Task } from '../Storage/TaskQueue';
|
||||
import { ActionError } from '../Errors';
|
||||
import { GameState } from '../Storage/GameState';
|
||||
|
||||
export default class GrabHeroAttributesAction extends ActionController {
|
||||
static NAME = 'grab_hero_attributes';
|
||||
private state: GameState;
|
||||
|
||||
constructor(state: GameState) {
|
||||
super();
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
@registerAction
|
||||
export class GrabHeroAttributesAction extends ActionController {
|
||||
async run(args: Args, task: Task): Promise<any> {
|
||||
const healthElement = jQuery(
|
||||
'#attributes .attribute.health .powervalue .value'
|
||||
|
@ -1,7 +1,6 @@
|
||||
import ActionController from './ActionController';
|
||||
import { ActionController, registerAction } from './ActionController';
|
||||
import { Args } from '../Common';
|
||||
import { Task } from '../Storage/TaskQueue';
|
||||
import { GameState } from '../Storage/GameState';
|
||||
import { trimPrefix } from '../utils';
|
||||
import { AbortTaskError } from '../Errors';
|
||||
|
||||
@ -13,15 +12,8 @@ interface Adventure {
|
||||
level: number;
|
||||
}
|
||||
|
||||
export default class SendOnAdventureAction extends ActionController {
|
||||
static NAME = 'send_on_adventure';
|
||||
private state: GameState;
|
||||
|
||||
constructor(state: GameState) {
|
||||
super();
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
@registerAction
|
||||
export class SendOnAdventureAction extends ActionController {
|
||||
async run(args: Args, task: Task): Promise<any> {
|
||||
const adventures = this.findAdventures();
|
||||
|
||||
|
@ -1,11 +1,10 @@
|
||||
import ActionController from './ActionController';
|
||||
import { ActionController, registerAction } from './ActionController';
|
||||
import { Args } from '../Common';
|
||||
import { TryLaterError } from '../Errors';
|
||||
import Scheduler from '../Scheduler';
|
||||
import { Task } from '../Storage/TaskQueue';
|
||||
|
||||
export default class UpgradeBuildingAction extends ActionController {
|
||||
static NAME = 'upgrade_building';
|
||||
@registerAction
|
||||
export class UpgradeBuildingAction extends ActionController {
|
||||
async run(args: Args, task: Task): Promise<any> {
|
||||
const btn = jQuery(
|
||||
'.upgradeButtonsContainer .section1 button.green.build'
|
||||
|
@ -1,25 +1,18 @@
|
||||
import { markPage, sleepShort, timestamp } from './utils';
|
||||
import UpgradeBuildingTask from './Task/UpgradeBuildingTask';
|
||||
import UpgradeBuildingAction from './Action/UpgradeBuildingAction';
|
||||
import {
|
||||
AbortTaskError,
|
||||
BuildingQueueFullError,
|
||||
TryLaterError,
|
||||
} from './Errors';
|
||||
import { TaskQueue, TaskList, Task, TaskId } from './Storage/TaskQueue';
|
||||
import { Task, TaskId, TaskList, TaskQueue } from './Storage/TaskQueue';
|
||||
import ActionQueue from './Storage/ActionQueue';
|
||||
import { Args, Command } from './Common';
|
||||
import TaskQueueRenderer from './TaskQueueRenderer';
|
||||
import ActionController from './Action/ActionController';
|
||||
import { ActionController, createAction } from './Action/ActionController';
|
||||
import TaskController from './Task/TaskController';
|
||||
import GoToPageAction from './Action/GoToPageAction';
|
||||
import CheckBuildingRemainingTimeAction from './Action/CheckBuildingRemainingTimeAction';
|
||||
import SendOnAdventureTask from './Task/SendOnAdventureTask';
|
||||
import GrabHeroAttributesAction from './Action/GrabHeroAttributesAction';
|
||||
import { GameState } from './Storage/GameState';
|
||||
import CompleteTaskAction from './Action/CompleteTaskAction';
|
||||
import SendOnAdventureAction from './Action/SendOnAdventureAction';
|
||||
import ClickButtonAction from './Action/ClickButtonAction';
|
||||
|
||||
export default class Scheduler {
|
||||
private readonly version: string;
|
||||
@ -91,7 +84,12 @@ export default class Scheduler {
|
||||
|
||||
private async processTaskCommand(task: Task) {
|
||||
const taskController = this.createTaskControllerByName(task.cmd.name);
|
||||
this.log('PROCESS TASK', task.cmd.name, task, taskController);
|
||||
this.log(
|
||||
'PROCESS TASK',
|
||||
taskController?.constructor.name,
|
||||
task,
|
||||
taskController
|
||||
);
|
||||
if (taskController) {
|
||||
taskController.run(task);
|
||||
}
|
||||
@ -99,7 +97,11 @@ export default class Scheduler {
|
||||
|
||||
private async processActionCommand(cmd: Command, task: Task) {
|
||||
const actionController = this.createActionControllerByName(cmd.name);
|
||||
this.log('PROCESS ACTION', cmd.name, actionController);
|
||||
this.log(
|
||||
'PROCESS ACTION',
|
||||
actionController?.constructor.name,
|
||||
actionController
|
||||
);
|
||||
if (actionController) {
|
||||
await this.runAction(actionController, cmd.args, task);
|
||||
}
|
||||
@ -136,31 +138,14 @@ export default class Scheduler {
|
||||
}
|
||||
|
||||
private createActionControllerByName(
|
||||
actonName: string
|
||||
actionName: string
|
||||
): ActionController | undefined {
|
||||
if (actonName === GoToPageAction.NAME) {
|
||||
return new GoToPageAction();
|
||||
const action = createAction(actionName, this.gameState, this);
|
||||
if (!action) {
|
||||
this.logError('ACTION NOT FOUND', actionName);
|
||||
return undefined;
|
||||
}
|
||||
if (actonName === ClickButtonAction.NAME) {
|
||||
return new ClickButtonAction();
|
||||
}
|
||||
if (actonName === CompleteTaskAction.NAME) {
|
||||
return new CompleteTaskAction(this);
|
||||
}
|
||||
if (actonName === UpgradeBuildingAction.NAME) {
|
||||
return new UpgradeBuildingAction();
|
||||
}
|
||||
if (actonName === CheckBuildingRemainingTimeAction.NAME) {
|
||||
return new CheckBuildingRemainingTimeAction();
|
||||
}
|
||||
if (actonName === GrabHeroAttributesAction.NAME) {
|
||||
return new GrabHeroAttributesAction(this.gameState);
|
||||
}
|
||||
if (actonName === SendOnAdventureAction.NAME) {
|
||||
return new SendOnAdventureAction(this.gameState);
|
||||
}
|
||||
this.logError('ACTION NOT FOUND', actonName);
|
||||
return undefined;
|
||||
return action;
|
||||
}
|
||||
|
||||
private async runAction(action: ActionController, args: Args, task: Task) {
|
||||
|
@ -2,11 +2,11 @@ import Scheduler from '../Scheduler';
|
||||
import { Args, Command } from '../Common';
|
||||
import { Task } from '../Storage/TaskQueue';
|
||||
import TaskController from './TaskController';
|
||||
import GoToPageAction from '../Action/GoToPageAction';
|
||||
import GrabHeroAttributesAction from '../Action/GrabHeroAttributesAction';
|
||||
import CompleteTaskAction from '../Action/CompleteTaskAction';
|
||||
import SendOnAdventureAction from '../Action/SendOnAdventureAction';
|
||||
import ClickButtonAction from '../Action/ClickButtonAction';
|
||||
import { GoToPageAction } from '../Action/GoToPageAction';
|
||||
import { GrabHeroAttributesAction } from '../Action/GrabHeroAttributesAction';
|
||||
import { CompleteTaskAction } from '../Action/CompleteTaskAction';
|
||||
import { SendOnAdventureAction } from '../Action/SendOnAdventureAction';
|
||||
import { ClickButtonAction } from '../Action/ClickButtonAction';
|
||||
|
||||
export default class SendOnAdventureTask extends TaskController {
|
||||
static NAME = 'send_on_adventure';
|
||||
@ -17,25 +17,21 @@ export default class SendOnAdventureTask extends TaskController {
|
||||
this.scheduler = scheduler;
|
||||
}
|
||||
|
||||
name(): string {
|
||||
return SendOnAdventureTask.NAME;
|
||||
}
|
||||
|
||||
run(task: Task) {
|
||||
const args: Args = { ...task.cmd.args, taskId: task.id };
|
||||
this.scheduler.scheduleActions([
|
||||
new Command(GoToPageAction.NAME, { ...args, path: 'hero.php' }),
|
||||
new Command(GrabHeroAttributesAction.NAME, args),
|
||||
new Command(GoToPageAction.NAME, {
|
||||
new Command(GoToPageAction.name, { ...args, path: 'hero.php' }),
|
||||
new Command(GrabHeroAttributesAction.name, args),
|
||||
new Command(GoToPageAction.name, {
|
||||
...args,
|
||||
path: '/hero.php?t=3',
|
||||
}),
|
||||
new Command(SendOnAdventureAction.NAME, args),
|
||||
new Command(ClickButtonAction.NAME, {
|
||||
new Command(SendOnAdventureAction.name, args),
|
||||
new Command(ClickButtonAction.name, {
|
||||
...args,
|
||||
selector: '.adventureSendButton button',
|
||||
}),
|
||||
new Command(CompleteTaskAction.NAME, args),
|
||||
new Command(CompleteTaskAction.name, args),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { Task } from '../Storage/TaskQueue';
|
||||
|
||||
export default abstract class TaskController {
|
||||
abstract name(): string;
|
||||
abstract run(task: Task);
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
import Scheduler from '../Scheduler';
|
||||
import UpgradeBuildingAction from '../Action/UpgradeBuildingAction';
|
||||
import { UpgradeBuildingAction } from '../Action/UpgradeBuildingAction';
|
||||
import { Args, Command } from '../Common';
|
||||
import { Task } from '../Storage/TaskQueue';
|
||||
import TaskController from './TaskController';
|
||||
import GoToPageAction from '../Action/GoToPageAction';
|
||||
import CheckBuildingRemainingTimeAction from '../Action/CheckBuildingRemainingTimeAction';
|
||||
import CompleteTaskAction from '../Action/CompleteTaskAction';
|
||||
import { GoToPageAction } from '../Action/GoToPageAction';
|
||||
import { CheckBuildingRemainingTimeAction } from '../Action/CheckBuildingRemainingTimeAction';
|
||||
import { CompleteTaskAction } from '../Action/CompleteTaskAction';
|
||||
|
||||
export default class UpgradeBuildingTask extends TaskController {
|
||||
static NAME = 'upgrade_building';
|
||||
@ -16,22 +16,18 @@ export default class UpgradeBuildingTask extends TaskController {
|
||||
this.scheduler = scheduler;
|
||||
}
|
||||
|
||||
name(): string {
|
||||
return UpgradeBuildingTask.NAME;
|
||||
}
|
||||
|
||||
run(task: Task) {
|
||||
console.log('RUN', UpgradeBuildingTask.NAME, 'with', task);
|
||||
const args: Args = { ...task.cmd.args, taskId: task.id };
|
||||
this.scheduler.scheduleActions([
|
||||
new Command(GoToPageAction.NAME, { ...args, path: '/dorf1.php' }),
|
||||
new Command(CheckBuildingRemainingTimeAction.NAME, args),
|
||||
new Command(GoToPageAction.NAME, {
|
||||
new Command(GoToPageAction.name, { ...args, path: '/dorf1.php' }),
|
||||
new Command(CheckBuildingRemainingTimeAction.name, args),
|
||||
new Command(GoToPageAction.name, {
|
||||
...args,
|
||||
path: '/build.php?id=' + args.id,
|
||||
}),
|
||||
new Command(UpgradeBuildingAction.NAME, args),
|
||||
new Command(CompleteTaskAction.NAME, args),
|
||||
new Command(UpgradeBuildingAction.name, args),
|
||||
new Command(CompleteTaskAction.name, args),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"experimentalDecorators": true,
|
||||
"isolatedModules": true,
|
||||
"module": "commonjs",
|
||||
"outDir": "./dist",
|
||||
|
Loading…
Reference in New Issue
Block a user