Add logger component

This commit is contained in:
Anton Vakhrushev 2020-04-12 19:05:01 +03:00
parent abde52449f
commit 9d85d07ff5
8 changed files with 88 additions and 73 deletions

View File

@ -5,6 +5,7 @@ import { Task } from '../Storage/TaskQueue';
import { clickUpgradeButton } from '../Page/BuildingPage'; import { clickUpgradeButton } from '../Page/BuildingPage';
import { grabResourceDeposits } from '../Page/SlotBlock'; import { grabResourceDeposits } from '../Page/SlotBlock';
import { UpgradeBuildingTask } from '../Task/UpgradeBuildingTask'; import { UpgradeBuildingTask } from '../Task/UpgradeBuildingTask';
import { ResourceDeposit } from '../Game';
@registerAction @registerAction
export class UpgradeResourceToLevel extends ActionController { export class UpgradeResourceToLevel extends ActionController {
@ -25,18 +26,19 @@ export class UpgradeResourceToLevel extends ActionController {
return; 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 const available = deposits
.sort((x, y) => x.level - y.level) .sort((x, y) => x.level - y.level)
.filter(dep => dep.ready) .filter(dep => dep.ready)
.filter( .filter(isDepositTaskNotInQueue);
dep =>
tasks.find(
t =>
t.name === UpgradeBuildingTask.name &&
t.args.villageId === villageId &&
t.args.buildId === dep.buildId
) === undefined
);
if (available.length === 0) { if (available.length === 0) {
throw new TryLaterError(task.id, 10 * 60, 'No available deposits'); throw new TryLaterError(task.id, 10 * 60, 'No available deposits');

View File

@ -13,6 +13,7 @@ import {
import Vue from 'vue'; import Vue from 'vue';
import DashboardApp from './Components/DashboardApp.vue'; import DashboardApp from './Components/DashboardApp.vue';
import { ResourcesToLevel } from '../Task/ResourcesToLevel'; import { ResourcesToLevel } from '../Task/ResourcesToLevel';
import { Logger } from '../Logger';
interface QuickAction { interface QuickAction {
label: string; label: string;
@ -22,17 +23,19 @@ interface QuickAction {
export class Dashboard { export class Dashboard {
private readonly version: string; private readonly version: string;
private scheduler: Scheduler; private scheduler: Scheduler;
private readonly logger;
constructor(version: string, scheduler: Scheduler) { constructor(version: string, scheduler: Scheduler) {
this.version = version; this.version = version;
this.scheduler = scheduler; this.scheduler = scheduler;
this.logger = new Logger(this.constructor.name);
} }
async run() { async run() {
await waitForLoad(); await waitForLoad();
const p = new URLParse(window.location.href, true); const p = new URLParse(window.location.href, true);
this.log('PARSED LOCATION', p); this.logger.log('PARSED LOCATION', p);
const villageId = grabActiveVillageId(); const villageId = grabActiveVillageId();
@ -116,12 +119,4 @@ export class Dashboard {
const n = new Notification(`Building ${buildId} scheduled`); const n = new Notification(`Building ${buildId} scheduled`);
setTimeout(() => n && n.close(), 4000); setTimeout(() => n && n.close(), 4000);
} }
private log(...args) {
console.log('SCHEDULER:', ...args);
}
private logError(...args) {
console.error(...args);
}
} }

22
src/Logger.ts Normal file
View 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);
}
}

View File

@ -3,20 +3,23 @@ import { UpgradeBuildingTask } from '../Task/UpgradeBuildingTask';
import { Scheduler } from '../Scheduler'; import { Scheduler } from '../Scheduler';
import { TrainTroopTask } from '../Task/TrainTroopTask'; import { TrainTroopTask } from '../Task/TrainTroopTask';
import { grabActiveVillageId } from './VillageBlock'; import { grabActiveVillageId } from './VillageBlock';
import { Logger } from '../Logger';
const QUARTERS_ID = 19; const QUARTERS_ID = 19;
export class BuildPage { export class BuildPage {
private scheduler: Scheduler; private scheduler: Scheduler;
private readonly buildId: number; private readonly buildId: number;
private readonly logger;
constructor(scheduler: Scheduler, buildId: number) { constructor(scheduler: Scheduler, buildId: number) {
this.scheduler = scheduler; this.scheduler = scheduler;
this.buildId = buildId; this.buildId = buildId;
this.logger = new Logger(this.constructor.name);
} }
run() { run() {
const buildTypeId = elClassId(jQuery('#build').attr('class') || '', 'gid'); 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(); this.createUpgradeButton();
if (buildTypeId === QUARTERS_ID) { if (buildTypeId === QUARTERS_ID) {
this.createTrainTroopButton(); this.createTrainTroopButton();
@ -45,7 +48,7 @@ export class BuildPage {
const troopBlocks = jQuery('#nonFavouriteTroops .action.troop:not(.empty) .innerTroopWrapper'); const troopBlocks = jQuery('#nonFavouriteTroops .action.troop:not(.empty) .innerTroopWrapper');
troopBlocks.each((idx, el) => { troopBlocks.each((idx, el) => {
const troopId = elClassId(jQuery(el).attr('class') || '', 'troop'); const troopId = elClassId(jQuery(el).attr('class') || '', 'troop');
console.log('TROOP', troopId); this.logger.log('TROOP', troopId);
if (troopId) { if (troopId) {
const id = uniqId(); const id = uniqId();
jQuery(el) jQuery(el)
@ -60,12 +63,12 @@ export class BuildPage {
} }
private onTrainTroopClick(buildId: number, troopId: number, el: HTMLElement) { 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 villageId = grabActiveVillageId();
const input = jQuery(el).find(`input[name="t${troopId}"]`); const input = jQuery(el).find(`input[name="t${troopId}"]`);
const count = Number(input.val()); const count = Number(input.val());
if (!isNaN(count) && count > 0) { 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)) { for (let n of split(count)) {
this.scheduler.scheduleTask(TrainTroopTask.name, { this.scheduler.scheduleTask(TrainTroopTask.name, {
villageId, villageId,
@ -76,12 +79,4 @@ export class BuildPage {
} }
} }
} }
private log(...args) {
console.log('BUILD PAGE:', ...args);
}
private logError(...args) {
console.error(...args);
}
} }

View File

@ -10,18 +10,21 @@ import { createTask } from './Task/TaskController';
import { SendOnAdventureTask } from './Task/SendOnAdventureTask'; import { SendOnAdventureTask } from './Task/SendOnAdventureTask';
import { GameState } from './Storage/GameState'; import { GameState } from './Storage/GameState';
import { BalanceHeroResourcesTask } from './Task/BalanceHeroResourcesTask'; import { BalanceHeroResourcesTask } from './Task/BalanceHeroResourcesTask';
import { Logger } from './Logger';
export class Scheduler { export class Scheduler {
private readonly version: string; private readonly version: string;
private taskQueue: TaskQueue; private taskQueue: TaskQueue;
private actionQueue: ActionQueue; private actionQueue: ActionQueue;
private gameState: GameState; private gameState: GameState;
private logger: Logger;
constructor(version: string) { constructor(version: string) {
this.version = version; this.version = version;
this.taskQueue = new TaskQueue(); this.taskQueue = new TaskQueue();
this.actionQueue = new ActionQueue(); this.actionQueue = new ActionQueue();
this.gameState = new GameState(); this.gameState = new GameState();
this.logger = new Logger(this.constructor.name);
} }
async run() { async run() {
@ -41,7 +44,7 @@ export class Scheduler {
} }
private renderTaskQueue() { private renderTaskQueue() {
this.log('RENDER TASK QUEUE'); this.logger.log('RENDER TASK QUEUE');
new TaskQueueRenderer().render(this.taskQueue.seeItems()); new TaskQueueRenderer().render(this.taskQueue.seeItems());
} }
@ -62,15 +65,15 @@ export class Scheduler {
// текущего таска нет, очищаем очередь действий по таску // текущего таска нет, очищаем очередь действий по таску
if (!taskCommand) { if (!taskCommand) {
this.log('NO ACTIVE TASK'); this.logger.log('NO ACTIVE TASK');
this.actionQueue.clear(); this.actionQueue.clear();
return; return;
} }
const actionCommand = this.actionQueue.pop(); const actionCommand = this.actionQueue.pop();
this.log('CURRENT TASK', taskCommand); this.logger.log('CURRENT TASK', taskCommand);
this.log('CURRENT ACTION', actionCommand); this.logger.log('CURRENT ACTION', actionCommand);
try { try {
if (actionCommand) { if (actionCommand) {
@ -87,21 +90,21 @@ export class Scheduler {
private async processActionCommand(cmd: Command, task: Task) { private async processActionCommand(cmd: Command, task: Task) {
const actionController = createAction(cmd.name, this.gameState, this); 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) { if (actionController) {
await actionController.run(cmd.args, task); await actionController.run(cmd.args, task);
} else { } else {
this.logWarn('ACTION NOT FOUND', cmd.name); this.logger.warn('ACTION NOT FOUND', cmd.name);
} }
} }
private async processTaskCommand(task: Task) { private async processTaskCommand(task: Task) {
const taskController = createTask(task.name, this); 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) { if (taskController) {
await taskController.run(task); await taskController.run(task);
} else { } else {
this.logWarn('TASK NOT FOUND', task.name); this.logger.warn('TASK NOT FOUND', task.name);
this.taskQueue.complete(task.id); this.taskQueue.complete(task.id);
} }
} }
@ -110,19 +113,19 @@ export class Scheduler {
this.actionQueue.clear(); this.actionQueue.clear();
if (err instanceof AbortTaskError) { if (err instanceof AbortTaskError) {
this.logWarn('ABORT TASK', err.taskId); this.logger.warn('ABORT TASK', err.taskId);
this.completeTask(err.taskId); this.completeTask(err.taskId);
return; return;
} }
if (err instanceof TryLaterError) { 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); this.taskQueue.postpone(err.taskId, timestamp() + err.seconds);
return; return;
} }
if (err instanceof BuildingQueueFullError) { 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( this.taskQueue.modify(
t => t.name === UpgradeBuildingTask.name && t.args.villageId === err.villageId, t => t.name === UpgradeBuildingTask.name && t.args.villageId === err.villageId,
t => t.withTime(timestamp() + err.seconds) t => t.withTime(timestamp() + err.seconds)
@ -131,11 +134,11 @@ export class Scheduler {
} }
if (err instanceof ActionError) { if (err instanceof ActionError) {
this.logWarn('ACTION ABORTED', err.message); this.logger.warn('ACTION ABORTED', err.message);
return; return;
} }
this.logError(err.message); this.logger.error(err.message);
throw err; throw err;
} }
@ -149,7 +152,7 @@ export class Scheduler {
} }
scheduleTask(name: string, args: Args): void { 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()); this.taskQueue.push(name, args, timestamp());
} }
@ -161,16 +164,4 @@ export class Scheduler {
scheduleActions(actions: Array<Command>): void { scheduleActions(actions: Array<Command>): void {
this.actionQueue.assign(actions); 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);
}
} }

View File

@ -1,4 +1,5 @@
import { Command } from '../Common'; import { Command } from '../Common';
import { Logger } from '../Logger';
const QUEUE_NAME = 'action_queue:v2'; const QUEUE_NAME = 'action_queue:v2';
@ -18,6 +19,12 @@ class State {
} }
export class ActionQueue { export class ActionQueue {
private readonly logger;
constructor() {
this.logger = new Logger(this.constructor.name);
}
pop(): Command | undefined { pop(): Command | undefined {
const state = this.getState(); const state = this.getState();
const first = state.pop(); const first = state.pop();
@ -46,7 +53,7 @@ export class ActionQueue {
} }
let parsed = JSON.parse(serialized) as State; let parsed = JSON.parse(serialized) as State;
this.log('STATE', parsed); this.logger.log('STATE', parsed);
return new State(parsed.items); return new State(parsed.items);
} }
@ -54,8 +61,4 @@ export class ActionQueue {
private flushState(state: State): void { private flushState(state: State): void {
localStorage.setItem(QUEUE_NAME, JSON.stringify(state)); localStorage.setItem(QUEUE_NAME, JSON.stringify(state));
} }
private log(...args) {
console.log('ACTION QUEUE:', ...args);
}
} }

View File

@ -1,3 +1,5 @@
import { Logger } from '../Logger';
const NAMESPACE = 'game_state:v1'; const NAMESPACE = 'game_state:v1';
function join(x: string, y: string) { function join(x: string, y: string) {
@ -5,8 +7,14 @@ function join(x: string, y: string) {
} }
export class GameState { export class GameState {
private readonly logger;
constructor() {
this.logger = new Logger(this.constructor.name);
}
get(key: string): any { get(key: string): any {
this.log('GET', key); this.logger.log('GET', key);
try { try {
const serialized = localStorage.getItem(join(NAMESPACE, key)); const serialized = localStorage.getItem(join(NAMESPACE, key));
return JSON.parse(serialized || 'null'); return JSON.parse(serialized || 'null');
@ -24,11 +32,7 @@ export class GameState {
set(key: string, value: any) { set(key: string, value: any) {
let serialized = JSON.stringify(value); let serialized = JSON.stringify(value);
this.log('SET', key, serialized); this.logger.log('SET', key, serialized);
localStorage.setItem(join(NAMESPACE, key), serialized); localStorage.setItem(join(NAMESPACE, key), serialized);
} }
private log(...args) {
console.log('GAME STATE:', ...args);
}
} }

View File

@ -1,5 +1,6 @@
import { Args } from '../Common'; import { Args } from '../Common';
import { uniqId } from '../utils'; import { uniqId } from '../utils';
import { Logger } from '../Logger';
const QUEUE_NAME = 'task_queue:v4'; const QUEUE_NAME = 'task_queue:v4';
@ -29,10 +30,16 @@ export class Task {
export type TaskList = Array<Task>; export type TaskList = Array<Task>;
export class TaskQueue { export class TaskQueue {
private readonly logger;
constructor() {
this.logger = new Logger(this.constructor.name);
}
push(name: string, args: Args, ts: number): Task { push(name: string, args: Args, ts: number): Task {
const id = uniqTaskId(); const id = uniqTaskId();
const task = new Task(id, ts, name, args); 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(); let items = this.getItems();
items.push(task); items.push(task);
this.flushItems(items); this.flushItems(items);
@ -70,7 +77,7 @@ export class TaskQueue {
postpone(id: TaskId, newTs: number) { postpone(id: TaskId, newTs: number) {
const [task, items] = this.shiftTask(id); const [task, items] = this.shiftTask(id);
if (task) { if (task) {
this.log('POSTPONE', task); this.logger.log('POSTPONE', task);
items.push(task.withTime(newTs)); items.push(task.withTime(newTs));
} }
this.flushItems(items); this.flushItems(items);
@ -117,8 +124,4 @@ export class TaskQueue {
const normalized = items.sort((x, y) => x.ts - y.ts); const normalized = items.sort((x, y) => x.ts - y.ts);
localStorage.setItem(QUEUE_NAME, JSON.stringify(normalized)); localStorage.setItem(QUEUE_NAME, JSON.stringify(normalized));
} }
private log(...args) {
console.log('TASK QUEUE:', ...args);
}
} }