Add "no implicit any" option and types

This commit is contained in:
Anton Vakhrushev 2020-05-01 13:29:52 +03:00
parent 418655ebff
commit e091a2170d
14 changed files with 72 additions and 67 deletions

View File

@ -11,7 +11,7 @@ import { VillageState } from '../State/VillageState';
import { Args } from '../Queue/Args'; import { Args } from '../Queue/Args';
import { Task } from '../Queue/TaskProvider'; import { Task } from '../Queue/TaskProvider';
function err(msg): never { function err(msg: string): never {
throw new ActionError(msg); throw new ActionError(msg);
} }
@ -101,7 +101,7 @@ export class SendResourcesAction extends ActionController {
return missing; return missing;
} }
private getResourcesForTransfer(recipientVillageId): Resources { private getResourcesForTransfer(recipientVillageId: number): Resources {
const senderResources = this.getSenderAvailableResources(); const senderResources = this.getSenderAvailableResources();
const recipientNeeds = this.getRecipientRequirements(recipientVillageId); const recipientNeeds = this.getRecipientRequirements(recipientVillageId);
const prepared = senderResources.min(recipientNeeds); const prepared = senderResources.min(recipientNeeds);

View File

@ -13,7 +13,7 @@ export class Container {
this.version = version; this.version = version;
} }
private _scheduler; private _scheduler: Scheduler | undefined;
get scheduler(): Scheduler { get scheduler(): Scheduler {
this._scheduler = this._scheduler =
@ -27,7 +27,7 @@ export class Container {
return this._scheduler; return this._scheduler;
} }
private _executor; private _executor: Executor | undefined;
get executor(): Executor { get executor(): Executor {
this._executor = this._executor =
@ -38,7 +38,7 @@ export class Container {
return this._executor; return this._executor;
} }
private _controlPanel; private _controlPanel: ControlPanel | undefined;
get controlPanel(): ControlPanel { get controlPanel(): ControlPanel {
this._controlPanel = this._controlPanel =

View File

@ -15,12 +15,13 @@ import { ResourcesToLevel } from './Task/ResourcesToLevel';
import { ConsoleLogger, Logger } from './Logger'; import { ConsoleLogger, Logger } from './Logger';
import { VillageState } from './State/VillageState'; import { VillageState } from './State/VillageState';
import { Resources } from './Core/Resources'; import { Resources } from './Core/Resources';
import { Village } from './Core/Village'; import { Coordinates, Village } from './Core/Village';
import { calcGatheringTimings } from './Core/GatheringTimings'; import { calcGatheringTimings } from './Core/GatheringTimings';
import { DataStorage } from './DataStorage'; import { DataStorage } from './DataStorage';
import { getBuildingPageAttributes, isBuildingPage } from './Page/PageDetectors'; import { getBuildingPageAttributes, isBuildingPage } from './Page/PageDetectors';
import { debounce } from 'debounce'; import { debounce } from 'debounce';
import { ExecutionState } from './State/ExecutionState'; import { ExecutionState } from './State/ExecutionState';
import { ResourceStorage } from './Core/ResourceStorage';
interface QuickAction { interface QuickAction {
label: string; label: string;
@ -42,7 +43,7 @@ export class ControlPanel {
await waitForLoad(); await waitForLoad();
const p = parseLocation(); const p = parseLocation();
this.logger.log('PARSED LOCATION', p); this.logger.info('PARSED LOCATION', p);
const villageId = grabActiveVillageId(); const villageId = grabActiveVillageId();
@ -51,7 +52,7 @@ export class ControlPanel {
const executionState = new ExecutionState(); const executionState = new ExecutionState();
const state = { const state: any = {
name: 'Dashboard', name: 'Dashboard',
version: this.version, version: this.version,
activeVillage: {}, activeVillage: {},
@ -125,7 +126,7 @@ export class ControlPanel {
this.createControlPanel(state); this.createControlPanel(state);
} }
private createControlPanel(state) { private createControlPanel(state: any) {
const appId = `app-${uniqId()}`; const appId = `app-${uniqId()}`;
jQuery('body').prepend(`<div id="${appId}"></div>`); jQuery('body').prepend(`<div id="${appId}"></div>`);
new Vue({ new Vue({
@ -135,7 +136,7 @@ export class ControlPanel {
}); });
} }
private createDepositsQuickActions(villageId) { private createDepositsQuickActions(villageId: number) {
const deposits = grabResourceDeposits(); const deposits = grabResourceDeposits();
if (deposits.length === 0) { if (deposits.length === 0) {
return []; return [];
@ -162,25 +163,25 @@ export class ControlPanel {
} }
class VillageController { class VillageController {
public readonly id; public readonly id: number;
public readonly name; public readonly name: string;
public readonly crd; public readonly crd: Coordinates;
public readonly active; public readonly active: boolean;
public readonly lumber; public readonly lumber: number;
public readonly clay; public readonly clay: number;
public readonly iron; public readonly iron: number;
public readonly crop; public readonly crop: number;
public readonly resources; public readonly resources: Resources;
public readonly performance; public readonly performance: Resources;
public readonly requiredResources: Resources; public readonly requiredResources: Resources;
public readonly requiredBalance: Resources; public readonly requiredBalance: Resources;
public readonly totalRequiredResources: Resources; public readonly totalRequiredResources: Resources;
public readonly totalRequiredBalance: Resources; public readonly totalRequiredBalance: Resources;
public readonly incomingResources: Resources; public readonly incomingResources: Resources;
public readonly storage; public readonly storage: ResourceStorage;
public readonly warehouse; public readonly warehouse: number;
public readonly granary; public readonly granary: number;
public readonly buildRemainingSeconds; public readonly buildRemainingSeconds: number;
constructor(village: Village, state: VillageState, scheduler: Scheduler) { constructor(village: Village, state: VillageState, scheduler: Scheduler) {
const resources = state.getResources(); const resources = state.getResources();

View File

@ -64,7 +64,7 @@ export class DataStorage {
const fullKey = join(NAMESPACE, this.name, key); const fullKey = join(NAMESPACE, this.name, key);
try { try {
const serialized = storage.getItem(fullKey); const serialized = storage.getItem(fullKey);
this.logger.log('GET', fullKey, serialized); this.logger.info('GET', fullKey, serialized);
return JSON.parse(serialized || 'null'); return JSON.parse(serialized || 'null');
} catch (e) { } catch (e) {
if (e instanceof SyntaxError) { if (e instanceof SyntaxError) {
@ -97,7 +97,7 @@ export class DataStorage {
set(key: string, value: any) { set(key: string, value: any) {
const fullKey = join(NAMESPACE, this.name, key); const fullKey = join(NAMESPACE, this.name, key);
let serialized = JSON.stringify(value); let serialized = JSON.stringify(value);
this.logger.log('SET', fullKey, serialized); this.logger.info('SET', fullKey, serialized);
storage.setItem(fullKey, serialized); storage.setItem(fullKey, serialized);
} }
} }

View File

@ -72,14 +72,14 @@ export class Executor {
// текущего таска нет, очищаем очередь действий по таску // текущего таска нет, очищаем очередь действий по таску
if (!task) { if (!task) {
this.logger.log('NO ACTIVE TASK'); this.logger.info('NO ACTIVE TASK');
this.scheduler.clearActions(); this.scheduler.clearActions();
return; return;
} }
const actionCommand = this.scheduler.nextAction(); const actionCommand = this.scheduler.nextAction();
this.logger.log('CURRENT JOB', 'TASK', task, 'ACTION', actionCommand); this.logger.info('CURRENT JOB', 'TASK', task, 'ACTION', actionCommand);
this.runGrabbers(); this.runGrabbers();
@ -98,7 +98,7 @@ export class Executor {
private async processActionCommand(cmd: Action, task: Task) { private async processActionCommand(cmd: Action, task: Task) {
const actionHandler = createActionHandler(cmd.name, this.scheduler); const actionHandler = createActionHandler(cmd.name, this.scheduler);
this.logger.log('PROCESS ACTION', cmd.name, actionHandler); this.logger.info('PROCESS ACTION', cmd.name, actionHandler);
if (cmd.args.taskId !== task.id) { if (cmd.args.taskId !== task.id) {
throw new ActionError(`Action task id ${cmd.args.taskId} not equal current task id ${task.id}`); throw new ActionError(`Action task id ${cmd.args.taskId} not equal current task id ${task.id}`);
} }
@ -112,7 +112,7 @@ export class Executor {
private async processTaskCommand(task: Task) { private async processTaskCommand(task: Task) {
const taskHandler = createTaskHandler(task.name, this.scheduler); const taskHandler = createTaskHandler(task.name, this.scheduler);
this.logger.log('PROCESS TASK', task.name, task, taskHandler); this.logger.info('PROCESS TASK', task.name, task, taskHandler);
if (taskHandler) { if (taskHandler) {
await taskHandler.run(task); await taskHandler.run(task);
} else { } else {
@ -147,7 +147,7 @@ export class Executor {
private runGrabbers() { private runGrabbers() {
try { try {
this.logger.log('Rug grabbers'); this.logger.info('Rug grabbers');
this.grabbers.grab(); this.grabbers.grab();
} catch (e) { } catch (e) {
this.logger.warn('Grabbers fails with', e.message); this.logger.warn('Grabbers fails with', e.message);

View File

@ -1,31 +1,31 @@
export abstract class Logger { export interface Logger {
abstract log(...args): void; info(...args: any[]): void;
abstract warn(...args): void; warn(...args: any[]): void;
abstract error(...args): void; error(...args: any[]): void;
} }
export class NullLogger extends Logger { export class NullLogger implements Logger {
log(...args): void {} info(...args: any[]): void {}
warn(...args): void {} warn(...args: any[]): void {}
error(...args): void {} error(...args: any[]): void {}
} }
export class ConsoleLogger extends Logger { export class ConsoleLogger implements Logger {
private readonly name: string; private readonly name: string;
constructor(name: string) { constructor(name: string) {
super();
this.name = name.toUpperCase(); this.name = name.toUpperCase();
} }
log(...args): void { info(...args: any[]): void {
console.log(this.name + ':', ...args); console.log(this.name + ':', ...args);
} }
warn(...args): void { warn(...args: any[]): void {
console.warn(this.name + ':', ...args); console.warn(this.name + ':', ...args);
} }
error(...args): void { error(...args: any[]): void {
console.error(this.name + ':', ...args); console.error(this.name + ':', ...args);
} }
} }

View File

@ -60,12 +60,12 @@ export function createUpgradeButton(onClickHandler: (resources: Resources) => vo
}); });
} }
function grabResourcesFromList($els) { function grabResourcesFromList($els: JQuery) {
const getText = n => const getText = (n: number) =>
jQuery($els.get(n)) jQuery($els.get(n))
.find('.value') .find('.value')
.text(); .text();
const grab = n => getNumber(getText(n)); const grab = (n: number) => getNumber(getText(n));
return new Resources(grab(0), grab(1), grab(2), grab(3)); return new Resources(grab(0), grab(1), grab(2), grab(3));
} }
@ -120,7 +120,9 @@ export function createSendResourcesButton(
<a id="${id1000}" href="#">x1000</a> <a id="${id1000}" href="#">x1000</a>
</div>`); </div>`);
const createHandler = (handler, scale) => evt => { const createHandler = (handler: (resources: Resources, crd: Coordinates, scale: number) => void, scale: number) => (
evt: JQuery.Event
) => {
evt.preventDefault(); evt.preventDefault();
const sendSelect = jQuery('#send_select'); const sendSelect = jQuery('#send_select');
const resources = new Resources( const resources = new Resources(

View File

@ -3,7 +3,7 @@ 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 { ConsoleLogger } from '../Logger'; import { ConsoleLogger, Logger } from '../Logger';
import { import {
createBuildButton, createBuildButton,
createSendResourcesButton, createSendResourcesButton,
@ -21,7 +21,7 @@ import { BuildingPageAttributes, isMarketSendResourcesPage } from './PageDetecto
export class BuildingPageController { export class BuildingPageController {
private scheduler: Scheduler; private scheduler: Scheduler;
private readonly attributes: BuildingPageAttributes; private readonly attributes: BuildingPageAttributes;
private readonly logger; private readonly logger: Logger;
constructor(scheduler: Scheduler, attributes: BuildingPageAttributes) { constructor(scheduler: Scheduler, attributes: BuildingPageAttributes) {
this.scheduler = scheduler; this.scheduler = scheduler;
@ -31,7 +31,7 @@ export class BuildingPageController {
run() { run() {
const { buildTypeId, sheetId } = this.attributes; const { buildTypeId, sheetId } = this.attributes;
this.logger.log('BUILD PAGE DETECTED', 'ID', this.attributes.buildId, this.attributes); this.logger.info('BUILD PAGE DETECTED', 'ID', this.attributes.buildId, this.attributes);
if (buildTypeId) { if (buildTypeId) {
createUpgradeButton(res => this.onScheduleUpgradeBuilding(res)); createUpgradeButton(res => this.onScheduleUpgradeBuilding(res));

View File

@ -35,7 +35,7 @@ export function grabActiveVillageId(): number {
return grabActiveVillage()?.id || 0; return grabActiveVillage()?.id || 0;
} }
function grabVillageInfo($el): Village { function grabVillageInfo($el: JQuery): Village {
const href = $el.attr('href'); const href = $el.attr('href');
const parsedHref = parseLocation(href || ''); const parsedHref = parseLocation(href || '');
const id = getNumber(parsedHref.query.newdid); const id = getNumber(parsedHref.query.newdid);

View File

@ -1,5 +1,5 @@
import { DataStorage } from '../DataStorage'; import { DataStorage } from '../DataStorage';
import {Task, TaskList, TaskProvider, uniqTaskId} from './TaskProvider'; import { Task, TaskList, TaskProvider, uniqTaskId } from './TaskProvider';
const NAMESPACE = 'tasks:v1'; const NAMESPACE = 'tasks:v1';
const QUEUE_NAME = 'queue'; const QUEUE_NAME = 'queue';

View File

@ -14,7 +14,7 @@ export class TaskQueue {
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.logger.log('PUSH TASK', id, ts, name, args); this.logger.info('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);

View File

@ -56,7 +56,7 @@ export class Scheduler {
} }
scheduleTask(name: string, args: Args, ts?: number | undefined): void { scheduleTask(name: string, args: Args, ts?: number | undefined): void {
this.logger.log('PUSH TASK', name, args, ts); this.logger.info('PUSH TASK', name, args, ts);
let insertedTs = calculateInsertTime(this.taskQueue.seeItems(), name, args, ts); let insertedTs = calculateInsertTime(this.taskQueue.seeItems(), name, args, ts);
this.taskQueue.push(name, args, insertedTs); this.taskQueue.push(name, args, insertedTs);
if (args.villageId) { if (args.villageId) {
@ -83,9 +83,9 @@ export class Scheduler {
} }
const villageId = task.args.villageId; const villageId = task.args.villageId;
const modifyTime = t => withTime(t, timestamp() + seconds); const modifyTime = (t: Task) => withTime(t, timestamp() + seconds);
const buildPred = t => sameVillage(villageId, t.args) && isBuildingTask(t.name); const buildPred = (t: Task) => sameVillage(villageId, t.args) && isBuildingTask(t.name);
const trainPred = t => sameVillage(villageId, t.args) && isTrainTroopTask(t.name); const trainPred = (t: Task) => sameVillage(villageId, t.args) && isTrainTroopTask(t.name);
if (isBuildingTask(task.name) && villageId) { if (isBuildingTask(task.name) && villageId) {
this.taskQueue.modify(buildPred, modifyTime); this.taskQueue.modify(buildPred, modifyTime);
@ -115,7 +115,7 @@ export class Scheduler {
this.actionQueue.clear(); this.actionQueue.clear();
} }
getVillageRequiredResources(villageId): Resources { getVillageRequiredResources(villageId: number): Resources {
const tasks = this.taskQueue const tasks = this.taskQueue
.seeItems() .seeItems()
.filter(t => sameVillage(villageId, t.args) && t.args.resources && t.name !== SendResourcesTask.name); .filter(t => sameVillage(villageId, t.args) && t.args.resources && t.name !== SendResourcesTask.name);
@ -123,10 +123,10 @@ export class Scheduler {
if (first && first.args.resources) { if (first && first.args.resources) {
return Resources.fromObject(first.args.resources); return Resources.fromObject(first.args.resources);
} }
return new Resources(0, 0, 0, 0); return Resources.zero();
} }
getTotalVillageRequiredResources(villageId): Resources { getTotalVillageRequiredResources(villageId: number): Resources {
const tasks = this.taskQueue const tasks = this.taskQueue
.seeItems() .seeItems()
.filter(t => sameVillage(villageId, t.args) && t.args.resources && t.name !== SendResourcesTask.name); .filter(t => sameVillage(villageId, t.args) && t.args.resources && t.name !== SendResourcesTask.name);
@ -135,8 +135,8 @@ export class Scheduler {
private reorderVillageTasks(villageId: number) { private reorderVillageTasks(villageId: number) {
const tasks = this.taskQueue.seeItems(); const tasks = this.taskQueue.seeItems();
const trainPred = t => isTrainTroopTask(t.name) && sameVillage(villageId, t.args); const trainPred = (t: Task) => isTrainTroopTask(t.name) && sameVillage(villageId, t.args);
const buildPred = t => isBuildingTask(t.name) && sameVillage(villageId, t.args); const buildPred = (t: Task) => isBuildingTask(t.name) && sameVillage(villageId, t.args);
const lastTrainTaskTs = lastTaskTime(tasks, trainPred); const lastTrainTaskTs = lastTaskTime(tasks, trainPred);
if (lastTrainTaskTs) { if (lastTrainTaskTs) {
this.taskQueue.modify(buildPred, t => withTime(t, lastTrainTaskTs + 1)); this.taskQueue.modify(buildPred, t => withTime(t, lastTrainTaskTs + 1));
@ -196,7 +196,8 @@ function calculateInsertTime(tasks: ImmutableTaskList, name: string, args: Args,
if (villageId && !insertedTs) { if (villageId && !insertedTs) {
for (let taskTypePred of TASK_TYPE_PREDICATES) { for (let taskTypePred of TASK_TYPE_PREDICATES) {
const sameVillageAndTypePred = t => taskTypePred(name) && t.args.villageId === villageId && t.name === name; const sameVillageAndTypePred = (t: Task) =>
taskTypePred(name) && t.args.villageId === villageId && t.name === name;
insertedTs = lastTaskTime(tasks, sameVillageAndTypePred); insertedTs = lastTaskTime(tasks, sameVillageAndTypePred);
if (insertedTs) { if (insertedTs) {
insertedTs += 1; insertedTs += 1;

View File

@ -6,18 +6,18 @@ import { Container } from './Container';
function main() { function main() {
const logger = new ConsoleLogger('Travian'); const logger = new ConsoleLogger('Travian');
logger.log('TRAVIAN AUTOMATION', TxtVersion); logger.info('TRAVIAN AUTOMATION', TxtVersion);
const container = new Container(TxtVersion); const container = new Container(TxtVersion);
const modeDetector = new ModeDetector(); const modeDetector = new ModeDetector();
if (modeDetector.isAuto()) { if (modeDetector.isAuto()) {
modeDetector.setAuto(); modeDetector.setAuto();
logger.log('AUTO MANAGEMENT ON'); logger.info('AUTO MANAGEMENT ON');
const executor = container.executor; const executor = container.executor;
executor.run(); executor.run();
} else { } else {
logger.log('NORMAL MODE'); logger.info('NORMAL MODE');
const controlPanel = container.controlPanel; const controlPanel = container.controlPanel;
controlPanel.run(); controlPanel.run();
} }

View File

@ -5,6 +5,7 @@
"isolatedModules": true, "isolatedModules": true,
"module": "commonjs", "module": "commonjs",
"outDir": "./dist", "outDir": "./dist",
"noImplicitAny": true,
"strictNullChecks": true, "strictNullChecks": true,
"strictPropertyInitialization": true, "strictPropertyInitialization": true,
"target": "es2018", "target": "es2018",