Add logger component
This commit is contained in:
		| @@ -5,6 +5,7 @@ import { Task } from '../Storage/TaskQueue'; | ||||
| import { clickUpgradeButton } from '../Page/BuildingPage'; | ||||
| import { grabResourceDeposits } from '../Page/SlotBlock'; | ||||
| import { UpgradeBuildingTask } from '../Task/UpgradeBuildingTask'; | ||||
| import { ResourceDeposit } from '../Game'; | ||||
|  | ||||
| @registerAction | ||||
| export class UpgradeResourceToLevel extends ActionController { | ||||
| @@ -25,18 +26,19 @@ export class UpgradeResourceToLevel extends ActionController { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         const isDepositTaskNotInQueue = (dep: ResourceDeposit) => | ||||
|             undefined === | ||||
|             tasks.find( | ||||
|                 task => | ||||
|                     task.name === UpgradeBuildingTask.name && | ||||
|                     task.args.villageId === villageId && | ||||
|                     task.args.buildId === dep.buildId | ||||
|             ); | ||||
|  | ||||
|         const available = deposits | ||||
|             .sort((x, y) => x.level - y.level) | ||||
|             .filter(dep => dep.ready) | ||||
|             .filter( | ||||
|                 dep => | ||||
|                     tasks.find( | ||||
|                         t => | ||||
|                             t.name === UpgradeBuildingTask.name && | ||||
|                             t.args.villageId === villageId && | ||||
|                             t.args.buildId === dep.buildId | ||||
|                     ) === undefined | ||||
|             ); | ||||
|             .filter(isDepositTaskNotInQueue); | ||||
|  | ||||
|         if (available.length === 0) { | ||||
|             throw new TryLaterError(task.id, 10 * 60, 'No available deposits'); | ||||
|   | ||||
| @@ -13,6 +13,7 @@ import { | ||||
| import Vue from 'vue'; | ||||
| import DashboardApp from './Components/DashboardApp.vue'; | ||||
| import { ResourcesToLevel } from '../Task/ResourcesToLevel'; | ||||
| import { Logger } from '../Logger'; | ||||
|  | ||||
| interface QuickAction { | ||||
|     label: string; | ||||
| @@ -22,17 +23,19 @@ interface QuickAction { | ||||
| export class Dashboard { | ||||
|     private readonly version: string; | ||||
|     private scheduler: Scheduler; | ||||
|     private readonly logger; | ||||
|  | ||||
|     constructor(version: string, scheduler: Scheduler) { | ||||
|         this.version = version; | ||||
|         this.scheduler = scheduler; | ||||
|         this.logger = new Logger(this.constructor.name); | ||||
|     } | ||||
|  | ||||
|     async run() { | ||||
|         await waitForLoad(); | ||||
|  | ||||
|         const p = new URLParse(window.location.href, true); | ||||
|         this.log('PARSED LOCATION', p); | ||||
|         this.logger.log('PARSED LOCATION', p); | ||||
|  | ||||
|         const villageId = grabActiveVillageId(); | ||||
|  | ||||
| @@ -116,12 +119,4 @@ export class Dashboard { | ||||
|         const n = new Notification(`Building ${buildId} scheduled`); | ||||
|         setTimeout(() => n && n.close(), 4000); | ||||
|     } | ||||
|  | ||||
|     private log(...args) { | ||||
|         console.log('SCHEDULER:', ...args); | ||||
|     } | ||||
|  | ||||
|     private logError(...args) { | ||||
|         console.error(...args); | ||||
|     } | ||||
| } | ||||
|   | ||||
							
								
								
									
										22
									
								
								src/Logger.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/Logger.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| export class Logger { | ||||
|     private readonly name: string; | ||||
|     constructor(name: string) { | ||||
|         this.name = name.toUpperCase(); | ||||
|     } | ||||
|  | ||||
|     log(...args): void { | ||||
|         console.log(this.name + ':', ...args); | ||||
|     } | ||||
|  | ||||
|     warn(...args): void { | ||||
|         console.warn(this.name + ':', ...args); | ||||
|     } | ||||
|  | ||||
|     error(...args): void { | ||||
|         console.error(this.name + ':', ...args); | ||||
|     } | ||||
|  | ||||
|     makeLogger(name: string) { | ||||
|         return new Logger(this.name + '.' + name); | ||||
|     } | ||||
| } | ||||
| @@ -3,20 +3,23 @@ import { UpgradeBuildingTask } from '../Task/UpgradeBuildingTask'; | ||||
| import { Scheduler } from '../Scheduler'; | ||||
| import { TrainTroopTask } from '../Task/TrainTroopTask'; | ||||
| import { grabActiveVillageId } from './VillageBlock'; | ||||
| import { Logger } from '../Logger'; | ||||
|  | ||||
| const QUARTERS_ID = 19; | ||||
|  | ||||
| export class BuildPage { | ||||
|     private scheduler: Scheduler; | ||||
|     private readonly buildId: number; | ||||
|     private readonly logger; | ||||
|     constructor(scheduler: Scheduler, buildId: number) { | ||||
|         this.scheduler = scheduler; | ||||
|         this.buildId = buildId; | ||||
|         this.logger = new Logger(this.constructor.name); | ||||
|     } | ||||
|  | ||||
|     run() { | ||||
|         const buildTypeId = elClassId(jQuery('#build').attr('class') || '', 'gid'); | ||||
|         this.log('BUILD PAGE DETECTED', 'ID', this.buildId, 'TYPE', buildTypeId); | ||||
|         this.logger.log('BUILD PAGE DETECTED', 'ID', this.buildId, 'TYPE', buildTypeId); | ||||
|         this.createUpgradeButton(); | ||||
|         if (buildTypeId === QUARTERS_ID) { | ||||
|             this.createTrainTroopButton(); | ||||
| @@ -45,7 +48,7 @@ export class BuildPage { | ||||
|         const troopBlocks = jQuery('#nonFavouriteTroops .action.troop:not(.empty) .innerTroopWrapper'); | ||||
|         troopBlocks.each((idx, el) => { | ||||
|             const troopId = elClassId(jQuery(el).attr('class') || '', 'troop'); | ||||
|             console.log('TROOP', troopId); | ||||
|             this.logger.log('TROOP', troopId); | ||||
|             if (troopId) { | ||||
|                 const id = uniqId(); | ||||
|                 jQuery(el) | ||||
| @@ -60,12 +63,12 @@ export class BuildPage { | ||||
|     } | ||||
|  | ||||
|     private onTrainTroopClick(buildId: number, troopId: number, el: HTMLElement) { | ||||
|         console.log('TRAIN TROOPERS', 'TROOP ID', troopId, 'BUILDING ID', buildId); | ||||
|         this.logger.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'); | ||||
|             this.logger.log('PREPARE TO TRAIN', count, 'TROOPERS'); | ||||
|             for (let n of split(count)) { | ||||
|                 this.scheduler.scheduleTask(TrainTroopTask.name, { | ||||
|                     villageId, | ||||
| @@ -76,12 +79,4 @@ export class BuildPage { | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private log(...args) { | ||||
|         console.log('BUILD PAGE:', ...args); | ||||
|     } | ||||
|  | ||||
|     private logError(...args) { | ||||
|         console.error(...args); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -10,18 +10,21 @@ import { createTask } from './Task/TaskController'; | ||||
| import { SendOnAdventureTask } from './Task/SendOnAdventureTask'; | ||||
| import { GameState } from './Storage/GameState'; | ||||
| import { BalanceHeroResourcesTask } from './Task/BalanceHeroResourcesTask'; | ||||
| import { Logger } from './Logger'; | ||||
|  | ||||
| export class Scheduler { | ||||
|     private readonly version: string; | ||||
|     private taskQueue: TaskQueue; | ||||
|     private actionQueue: ActionQueue; | ||||
|     private gameState: GameState; | ||||
|     private logger: Logger; | ||||
|  | ||||
|     constructor(version: string) { | ||||
|         this.version = version; | ||||
|         this.taskQueue = new TaskQueue(); | ||||
|         this.actionQueue = new ActionQueue(); | ||||
|         this.gameState = new GameState(); | ||||
|         this.logger = new Logger(this.constructor.name); | ||||
|     } | ||||
|  | ||||
|     async run() { | ||||
| @@ -41,7 +44,7 @@ export class Scheduler { | ||||
|     } | ||||
|  | ||||
|     private renderTaskQueue() { | ||||
|         this.log('RENDER TASK QUEUE'); | ||||
|         this.logger.log('RENDER TASK QUEUE'); | ||||
|         new TaskQueueRenderer().render(this.taskQueue.seeItems()); | ||||
|     } | ||||
|  | ||||
| @@ -62,15 +65,15 @@ export class Scheduler { | ||||
|  | ||||
|         // текущего таска нет, очищаем очередь действий по таску | ||||
|         if (!taskCommand) { | ||||
|             this.log('NO ACTIVE TASK'); | ||||
|             this.logger.log('NO ACTIVE TASK'); | ||||
|             this.actionQueue.clear(); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         const actionCommand = this.actionQueue.pop(); | ||||
|  | ||||
|         this.log('CURRENT TASK', taskCommand); | ||||
|         this.log('CURRENT ACTION', actionCommand); | ||||
|         this.logger.log('CURRENT TASK', taskCommand); | ||||
|         this.logger.log('CURRENT ACTION', actionCommand); | ||||
|  | ||||
|         try { | ||||
|             if (actionCommand) { | ||||
| @@ -87,21 +90,21 @@ export class Scheduler { | ||||
|  | ||||
|     private async processActionCommand(cmd: Command, task: Task) { | ||||
|         const actionController = createAction(cmd.name, this.gameState, this); | ||||
|         this.log('PROCESS ACTION', cmd.name, actionController); | ||||
|         this.logger.log('PROCESS ACTION', cmd.name, actionController); | ||||
|         if (actionController) { | ||||
|             await actionController.run(cmd.args, task); | ||||
|         } else { | ||||
|             this.logWarn('ACTION NOT FOUND', cmd.name); | ||||
|             this.logger.warn('ACTION NOT FOUND', cmd.name); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private async processTaskCommand(task: Task) { | ||||
|         const taskController = createTask(task.name, this); | ||||
|         this.log('PROCESS TASK', task.name, task, taskController); | ||||
|         this.logger.log('PROCESS TASK', task.name, task, taskController); | ||||
|         if (taskController) { | ||||
|             await taskController.run(task); | ||||
|         } else { | ||||
|             this.logWarn('TASK NOT FOUND', task.name); | ||||
|             this.logger.warn('TASK NOT FOUND', task.name); | ||||
|             this.taskQueue.complete(task.id); | ||||
|         } | ||||
|     } | ||||
| @@ -110,19 +113,19 @@ export class Scheduler { | ||||
|         this.actionQueue.clear(); | ||||
|  | ||||
|         if (err instanceof AbortTaskError) { | ||||
|             this.logWarn('ABORT TASK', err.taskId); | ||||
|             this.logger.warn('ABORT TASK', err.taskId); | ||||
|             this.completeTask(err.taskId); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (err instanceof TryLaterError) { | ||||
|             this.logWarn('TRY', err.taskId, 'AFTER', err.seconds); | ||||
|             this.logger.warn('TRY', err.taskId, 'AFTER', err.seconds); | ||||
|             this.taskQueue.postpone(err.taskId, timestamp() + err.seconds); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (err instanceof BuildingQueueFullError) { | ||||
|             this.logWarn('BUILDING QUEUE FULL, TRY ALL AFTER', err.seconds); | ||||
|             this.logger.warn('BUILDING QUEUE FULL, TRY ALL AFTER', err.seconds); | ||||
|             this.taskQueue.modify( | ||||
|                 t => t.name === UpgradeBuildingTask.name && t.args.villageId === err.villageId, | ||||
|                 t => t.withTime(timestamp() + err.seconds) | ||||
| @@ -131,11 +134,11 @@ export class Scheduler { | ||||
|         } | ||||
|  | ||||
|         if (err instanceof ActionError) { | ||||
|             this.logWarn('ACTION ABORTED', err.message); | ||||
|             this.logger.warn('ACTION ABORTED', err.message); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         this.logError(err.message); | ||||
|         this.logger.error(err.message); | ||||
|         throw err; | ||||
|     } | ||||
|  | ||||
| @@ -149,7 +152,7 @@ export class Scheduler { | ||||
|     } | ||||
|  | ||||
|     scheduleTask(name: string, args: Args): void { | ||||
|         this.log('PUSH TASK', name, args); | ||||
|         this.logger.log('PUSH TASK', name, args); | ||||
|         this.taskQueue.push(name, args, timestamp()); | ||||
|     } | ||||
|  | ||||
| @@ -161,16 +164,4 @@ export class Scheduler { | ||||
|     scheduleActions(actions: Array<Command>): void { | ||||
|         this.actionQueue.assign(actions); | ||||
|     } | ||||
|  | ||||
|     private log(...args) { | ||||
|         console.log('SCHEDULER:', ...args); | ||||
|     } | ||||
|  | ||||
|     private logWarn(...args) { | ||||
|         console.warn('SCHEDULER:', ...args); | ||||
|     } | ||||
|  | ||||
|     private logError(...args) { | ||||
|         console.error('SCHEDULER:', ...args); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| import { Command } from '../Common'; | ||||
| import { Logger } from '../Logger'; | ||||
|  | ||||
| const QUEUE_NAME = 'action_queue:v2'; | ||||
|  | ||||
| @@ -18,6 +19,12 @@ class State { | ||||
| } | ||||
|  | ||||
| export class ActionQueue { | ||||
|     private readonly logger; | ||||
|  | ||||
|     constructor() { | ||||
|         this.logger = new Logger(this.constructor.name); | ||||
|     } | ||||
|  | ||||
|     pop(): Command | undefined { | ||||
|         const state = this.getState(); | ||||
|         const first = state.pop(); | ||||
| @@ -46,7 +53,7 @@ export class ActionQueue { | ||||
|         } | ||||
|  | ||||
|         let parsed = JSON.parse(serialized) as State; | ||||
|         this.log('STATE', parsed); | ||||
|         this.logger.log('STATE', parsed); | ||||
|  | ||||
|         return new State(parsed.items); | ||||
|     } | ||||
| @@ -54,8 +61,4 @@ export class ActionQueue { | ||||
|     private flushState(state: State): void { | ||||
|         localStorage.setItem(QUEUE_NAME, JSON.stringify(state)); | ||||
|     } | ||||
|  | ||||
|     private log(...args) { | ||||
|         console.log('ACTION QUEUE:', ...args); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,3 +1,5 @@ | ||||
| import { Logger } from '../Logger'; | ||||
|  | ||||
| const NAMESPACE = 'game_state:v1'; | ||||
|  | ||||
| function join(x: string, y: string) { | ||||
| @@ -5,8 +7,14 @@ function join(x: string, y: string) { | ||||
| } | ||||
|  | ||||
| export class GameState { | ||||
|     private readonly logger; | ||||
|  | ||||
|     constructor() { | ||||
|         this.logger = new Logger(this.constructor.name); | ||||
|     } | ||||
|  | ||||
|     get(key: string): any { | ||||
|         this.log('GET', key); | ||||
|         this.logger.log('GET', key); | ||||
|         try { | ||||
|             const serialized = localStorage.getItem(join(NAMESPACE, key)); | ||||
|             return JSON.parse(serialized || 'null'); | ||||
| @@ -24,11 +32,7 @@ export class GameState { | ||||
|  | ||||
|     set(key: string, value: any) { | ||||
|         let serialized = JSON.stringify(value); | ||||
|         this.log('SET', key, serialized); | ||||
|         this.logger.log('SET', key, serialized); | ||||
|         localStorage.setItem(join(NAMESPACE, key), serialized); | ||||
|     } | ||||
|  | ||||
|     private log(...args) { | ||||
|         console.log('GAME STATE:', ...args); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| import { Args } from '../Common'; | ||||
| import { uniqId } from '../utils'; | ||||
| import { Logger } from '../Logger'; | ||||
|  | ||||
| const QUEUE_NAME = 'task_queue:v4'; | ||||
|  | ||||
| @@ -29,10 +30,16 @@ export class Task { | ||||
| export type TaskList = Array<Task>; | ||||
|  | ||||
| export class TaskQueue { | ||||
|     private readonly logger; | ||||
|  | ||||
|     constructor() { | ||||
|         this.logger = new Logger(this.constructor.name); | ||||
|     } | ||||
|  | ||||
|     push(name: string, args: Args, ts: number): Task { | ||||
|         const id = uniqTaskId(); | ||||
|         const task = new Task(id, ts, name, args); | ||||
|         this.log('PUSH TASK', id, ts, name, args); | ||||
|         this.logger.log('PUSH TASK', id, ts, name, args); | ||||
|         let items = this.getItems(); | ||||
|         items.push(task); | ||||
|         this.flushItems(items); | ||||
| @@ -70,7 +77,7 @@ export class TaskQueue { | ||||
|     postpone(id: TaskId, newTs: number) { | ||||
|         const [task, items] = this.shiftTask(id); | ||||
|         if (task) { | ||||
|             this.log('POSTPONE', task); | ||||
|             this.logger.log('POSTPONE', task); | ||||
|             items.push(task.withTime(newTs)); | ||||
|         } | ||||
|         this.flushItems(items); | ||||
| @@ -117,8 +124,4 @@ export class TaskQueue { | ||||
|         const normalized = items.sort((x, y) => x.ts - y.ts); | ||||
|         localStorage.setItem(QUEUE_NAME, JSON.stringify(normalized)); | ||||
|     } | ||||
|  | ||||
|     private log(...args) { | ||||
|         console.log('TASK QUEUE:', ...args); | ||||
|     } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user