diff --git a/src/Action/ActionController.ts b/src/Action/ActionController.ts index 8ca1d22..d8c7a4e 100644 --- a/src/Action/ActionController.ts +++ b/src/Action/ActionController.ts @@ -1,11 +1,11 @@ import { Scheduler } from '../Scheduler'; import { taskError, TryLaterError } from '../Errors'; import { grabActiveVillageId } from '../Page/VillageBlock'; -import { aroundMinutes } from '../utils'; import { Args } from '../Queue/Args'; import { Task } from '../Queue/TaskProvider'; import { VillageStorage } from '../Storage/VillageStorage'; import { VillageFactory } from '../VillageFactory'; +import { aroundMinutes } from '../Helpers/Time'; const actionMap: { [name: string]: Function | undefined } = {}; diff --git a/src/Action/BuildBuildingAction.ts b/src/Action/BuildBuildingAction.ts index c8f13ea..c24c65e 100644 --- a/src/Action/BuildBuildingAction.ts +++ b/src/Action/BuildBuildingAction.ts @@ -1,9 +1,9 @@ import { ActionController, registerAction } from './ActionController'; import { GrabError, taskError, TryLaterError } from '../Errors'; import { clickBuildButton } from '../Page/BuildingPage/BuildingPage'; -import { aroundMinutes } from '../utils'; import { Args } from '../Queue/Args'; import { Task } from '../Queue/TaskProvider'; +import { aroundMinutes } from '../Helpers/Time'; @registerAction export class BuildBuildingAction extends ActionController { diff --git a/src/Action/CelebrationAction.ts b/src/Action/CelebrationAction.ts index dce3d56..ad0bd7a 100644 --- a/src/Action/CelebrationAction.ts +++ b/src/Action/CelebrationAction.ts @@ -1,9 +1,9 @@ import { ActionController, registerAction } from './ActionController'; import { GrabError, TryLaterError } from '../Errors'; -import { aroundMinutes } from '../utils'; import { Args } from '../Queue/Args'; import { Task } from '../Queue/TaskProvider'; import { clickCelebrationButton } from '../Page/BuildingPage/GuildHallPage'; +import { aroundMinutes } from '../Helpers/Time'; @registerAction export class CelebrationAction extends ActionController { diff --git a/src/Action/FindSendResourcesPath.ts b/src/Action/FindSendResourcesPath.ts index e5cd59e..9d18c97 100644 --- a/src/Action/FindSendResourcesPath.ts +++ b/src/Action/FindSendResourcesPath.ts @@ -2,7 +2,6 @@ import { ActionController, registerAction } from './ActionController'; import { FailTaskError, taskError, TryLaterError } from '../Errors'; import { Resources } from '../Core/Resources'; import { Coordinates } from '../Core/Village'; -import { aroundMinutes, timestamp } from '../utils'; import { Args } from '../Queue/Args'; import { Task } from '../Queue/TaskProvider'; import { clickSendButton, fillSendResourcesForm } from '../Page/BuildingPage/MarketPage'; @@ -17,6 +16,7 @@ import { import { ResourceTransferStorage } from '../Storage/ResourceTransferStorage'; import { path } from '../Helpers/Path'; import { MARKET_ID } from '../Core/Buildings'; +import { aroundMinutes, timestamp } from '../Helpers/Time'; @registerAction export class FindSendResourcesPath extends ActionController { diff --git a/src/Action/ForgeImprovementAction.ts b/src/Action/ForgeImprovementAction.ts index 98f0128..bf4208b 100644 --- a/src/Action/ForgeImprovementAction.ts +++ b/src/Action/ForgeImprovementAction.ts @@ -1,9 +1,9 @@ import { ActionController, registerAction } from './ActionController'; import { GrabError, taskError, TryLaterError } from '../Errors'; -import { aroundMinutes } from '../utils'; import { Args } from '../Queue/Args'; import { Task } from '../Queue/TaskProvider'; import { clickResearchButton } from '../Page/BuildingPage/ForgePage'; +import { aroundMinutes } from '../Helpers/Time'; @registerAction export class ForgeImprovementAction extends ActionController { diff --git a/src/Action/SendOnAdventureAction.ts b/src/Action/SendOnAdventureAction.ts index 84f236d..c46d428 100644 --- a/src/Action/SendOnAdventureAction.ts +++ b/src/Action/SendOnAdventureAction.ts @@ -1,8 +1,8 @@ import { ActionController, registerAction } from './ActionController'; -import { trimPrefix } from '../utils'; import { AbortTaskError } from '../Errors'; import { Args } from '../Queue/Args'; import { Task } from '../Queue/TaskProvider'; +import { trimPrefix } from '../Helpers/Convert'; const CONFIG = [ { level: 0, health: 60 }, diff --git a/src/Action/TrainTrooperAction.ts b/src/Action/TrainTrooperAction.ts index d8d7916..9e8b727 100644 --- a/src/Action/TrainTrooperAction.ts +++ b/src/Action/TrainTrooperAction.ts @@ -1,6 +1,5 @@ import { ActionController, registerAction } from './ActionController'; import { taskError, TryLaterError } from '../Errors'; -import { aroundMinutes, randomInRange } from '../utils'; import { Args } from '../Queue/Args'; import { Task } from '../Queue/TaskProvider'; import { @@ -10,6 +9,8 @@ import { } from '../Page/BuildingPage/TrooperPage'; import { TrainTroopTask } from '../Task/TrainTroopTask'; import { Resources } from '../Core/Resources'; +import { randomInRange } from '../Helpers/Random'; +import { aroundMinutes } from '../Helpers/Time'; @registerAction export class TrainTrooperAction extends ActionController { diff --git a/src/Action/UpgradeBuildingAction.ts b/src/Action/UpgradeBuildingAction.ts index b16a94d..500c119 100644 --- a/src/Action/UpgradeBuildingAction.ts +++ b/src/Action/UpgradeBuildingAction.ts @@ -1,9 +1,9 @@ import { ActionController, registerAction } from './ActionController'; import { GrabError, TryLaterError } from '../Errors'; import { clickUpgradeButton } from '../Page/BuildingPage/BuildingPage'; -import { aroundMinutes } from '../utils'; import { Args } from '../Queue/Args'; import { Task } from '../Queue/TaskProvider'; +import { aroundMinutes } from '../Helpers/Time'; @registerAction export class UpgradeBuildingAction extends ActionController { diff --git a/src/Action/UpgradeResourceToLevel.ts b/src/Action/UpgradeResourceToLevel.ts index 03f95b7..b1b4664 100644 --- a/src/Action/UpgradeResourceToLevel.ts +++ b/src/Action/UpgradeResourceToLevel.ts @@ -2,10 +2,11 @@ import { ActionController, registerAction } from './ActionController'; import { ActionError, taskError, TryLaterError } from '../Errors'; import { grabResourceSlots } from '../Page/SlotBlock'; import { UpgradeBuildingTask } from '../Task/UpgradeBuildingTask'; -import { aroundMinutes, getNumber } from '../utils'; import { Args } from '../Queue/Args'; import { Task } from '../Queue/TaskProvider'; import { ResourceSlot } from '../Core/Slot'; +import { getNumber } from '../Helpers/Convert'; +import { aroundMinutes } from '../Helpers/Time'; @registerAction export class UpgradeResourceToLevel extends ActionController { diff --git a/src/ControlPanel.ts b/src/ControlPanel.ts index c36fee5..d3e6d9e 100644 --- a/src/ControlPanel.ts +++ b/src/ControlPanel.ts @@ -1,4 +1,3 @@ -import { notify, parseLocation, timestamp, uniqId, waitForLoad } from './utils'; import { Scheduler } from './Scheduler'; import { BuildingPageController } from './Page/BuildingPageController'; import { UpgradeBuildingTask } from './Task/UpgradeBuildingTask'; @@ -21,6 +20,9 @@ import { Task } from './Queue/TaskProvider'; import { Action } from './Queue/ActionQueue'; import { createStore } from './DashboardView/Store'; import { VillageFactory } from './VillageFactory'; +import { uniqId } from './Helpers/Identity'; +import { timestamp } from './Helpers/Time'; +import { notify, parseLocation, waitForLoad } from './Helpers/Browser'; Vue.use(Vuex); diff --git a/src/DashboardView/LogList.vue b/src/DashboardView/LogList.vue index 1c1c2d0..ea5511b 100644 --- a/src/DashboardView/LogList.vue +++ b/src/DashboardView/LogList.vue @@ -13,8 +13,8 @@ <script> import { mapGetters } from 'vuex'; -import * as dateFormat from 'dateformat'; import { Mutations } from './Store'; +import { formatDate } from '../Helpers/Format'; export default { computed: { @@ -30,8 +30,7 @@ export default { }; }, formatDate(ts) { - const d = new Date(ts * 1000); - return dateFormat(d, 'HH:MM:ss'); + return formatDate(ts); }, close() { this.$store.commit(Mutations.hideLogs); diff --git a/src/DashboardView/Store.ts b/src/DashboardView/Store.ts index c17e15b..f9248af 100644 --- a/src/DashboardView/Store.ts +++ b/src/DashboardView/Store.ts @@ -1,9 +1,10 @@ import Vuex from 'vuex'; import { VillageSettings, VillageSettingsDefaults } from '../Core/Village'; -import { getNumber, notify } from '../utils'; import { VillageStorage } from '../Storage/VillageStorage'; import { VillageFactory } from '../VillageFactory'; import { StorageContainer } from '../Storage/StorageContainer'; +import { getNumber } from '../Helpers/Convert'; +import { notify } from '../Helpers/Browser'; export enum Mutations { showLogs = 'showLogs', diff --git a/src/DashboardView/TaskList.vue b/src/DashboardView/TaskList.vue index 6d4c52d..d4c5f9d 100644 --- a/src/DashboardView/TaskList.vue +++ b/src/DashboardView/TaskList.vue @@ -42,7 +42,7 @@ </template> <script> -import * as dateFormat from 'dateformat'; +import { formatDate } from '../Helpers/Format'; export default { data() { @@ -61,8 +61,7 @@ export default { }, methods: { formatDate(ts) { - const d = new Date(ts * 1000); - return dateFormat(d, 'HH:MM:ss'); + return formatDate(ts); }, isThisVillageTask(task) { const taskVillageId = (task.args || {}).villageId; diff --git a/src/Executor.ts b/src/Executor.ts index ff7435e..bbe55f1 100644 --- a/src/Executor.ts +++ b/src/Executor.ts @@ -1,4 +1,3 @@ -import { markPage, sleepMicro, timestamp, waitForLoad } from './utils'; import { AbortTaskError, ActionError, @@ -18,6 +17,8 @@ import { Action } from './Queue/ActionQueue'; import { Task } from './Queue/TaskProvider'; import { createTaskHandler } from './Task/TaskMap'; import { VillageFactory } from './VillageFactory'; +import { sleepMicro, timestamp } from './Helpers/Time'; +import { markPage, waitForLoad } from './Helpers/Browser'; export interface ExecutionSettings { pauseTs: number; diff --git a/src/Grabber/ForgePageGrabber.ts b/src/Grabber/ForgePageGrabber.ts index d0b79a9..3fdd18b 100644 --- a/src/Grabber/ForgePageGrabber.ts +++ b/src/Grabber/ForgePageGrabber.ts @@ -3,7 +3,7 @@ import { getBuildingPageAttributes, isForgePage } from '../Page/PageDetector'; import { ContractType } from '../Core/Contract'; import { grabImprovementContracts, grabRemainingSeconds } from '../Page/BuildingPage/ForgePage'; import { ProductionQueue } from '../Core/ProductionQueue'; -import { timestamp } from '../utils'; +import { timestamp } from '../Helpers/Time'; export class ForgePageGrabber extends Grabber { grab(): void { diff --git a/src/Grabber/GuildHallPageGrabber.ts b/src/Grabber/GuildHallPageGrabber.ts index de5529e..81885d6 100644 --- a/src/Grabber/GuildHallPageGrabber.ts +++ b/src/Grabber/GuildHallPageGrabber.ts @@ -2,7 +2,7 @@ import { Grabber } from './Grabber'; import { isGuildHallPage } from '../Page/PageDetector'; import { grabRemainingSeconds } from '../Page/BuildingPage/GuildHallPage'; import { ProductionQueue } from '../Core/ProductionQueue'; -import { timestamp } from '../utils'; +import { timestamp } from '../Helpers/Time'; export class GuildHallPageGrabber extends Grabber { grab(): void { diff --git a/src/Grabber/VillageBuildingsPageGrabber.ts b/src/Grabber/VillageBuildingsPageGrabber.ts index c27b11e..16fca03 100644 --- a/src/Grabber/VillageBuildingsPageGrabber.ts +++ b/src/Grabber/VillageBuildingsPageGrabber.ts @@ -1,6 +1,6 @@ import { Grabber } from './Grabber'; -import { parseLocation } from '../utils'; import { grabBuildingSlots } from '../Page/SlotBlock'; +import { parseLocation } from '../Helpers/Browser'; export class VillageBuildingsPageGrabber extends Grabber { grab(): void { diff --git a/src/Grabber/VillageOverviewPageGrabber.ts b/src/Grabber/VillageOverviewPageGrabber.ts index b17fce0..8097d59 100644 --- a/src/Grabber/VillageOverviewPageGrabber.ts +++ b/src/Grabber/VillageOverviewPageGrabber.ts @@ -1,10 +1,11 @@ import { Grabber } from './Grabber'; import { grabBuildingQueueInfo, grabResourcesPerformance } from '../Page/VillageBlock'; -import { parseLocation, timestamp } from '../utils'; import { GrabError } from '../Errors'; import { ProductionQueue } from '../Core/ProductionQueue'; import { grabResourceSlots } from '../Page/SlotBlock'; import { BuildingQueueInfo } from '../Core/BuildingQueueInfo'; +import { timestamp } from '../Helpers/Time'; +import { parseLocation } from '../Helpers/Browser'; export class VillageOverviewPageGrabber extends Grabber { grab(): void { diff --git a/src/Helpers/Browser.ts b/src/Helpers/Browser.ts new file mode 100644 index 0000000..0646481 --- /dev/null +++ b/src/Helpers/Browser.ts @@ -0,0 +1,31 @@ +import * as URLParse from 'url-parse'; + +export async function waitForLoad() { + return new Promise(resolve => jQuery(resolve)); +} + +export function parseLocation(location?: string | undefined) { + return new URLParse(location || window.location.href, true); +} + +export function notify(msg: string): void { + const n = new Notification(msg); + setTimeout(() => n && n.close(), 4000); +} + +export function markPage(text: string, version: string) { + jQuery('body').append( + '<div style="' + + 'position: absolute; ' + + 'top: 0; left: 0; ' + + 'background-color: white; ' + + 'font-size: 24px; ' + + 'z-index: 9999; ' + + 'padding: 8px 6px; ' + + 'color: black">' + + text + + ' ' + + version + + '</div>' + ); +} diff --git a/src/Helpers/Collection.ts b/src/Helpers/Collection.ts new file mode 100644 index 0000000..1623382 --- /dev/null +++ b/src/Helpers/Collection.ts @@ -0,0 +1,5 @@ +import * as _ from 'underscore'; + +export function first<T>(items: ReadonlyArray<T>): T | undefined { + return _.first(items); +} diff --git a/src/Helpers/Convert.ts b/src/Helpers/Convert.ts new file mode 100644 index 0000000..369b077 --- /dev/null +++ b/src/Helpers/Convert.ts @@ -0,0 +1,30 @@ +export function trimPrefix(text: string, prefix: string): string { + return text.startsWith(prefix) ? text.substr(prefix.length) : text; +} + +export function elClassId(classes: string | undefined, prefix: string): number | undefined { + if (classes === undefined) { + return undefined; + } + let result: number | undefined = undefined; + classes.split(/\s/).forEach(part => { + const match = part.match(new RegExp(prefix + '(\\d+)')); + if (match) { + result = toNumber(match[1]); + } + }); + return result; +} + +export function toNumber(value: any): number | undefined { + const normalized = String(value) + .replace('\u2212', '\u002d') // minus to hyphen-minus + .replace(/[^0-9\u002d]/g, ''); + const converted = Number(normalized); + return isNaN(converted) ? undefined : converted; +} + +export function getNumber(value: any, def: number = 0): number { + const converted = toNumber(value); + return converted === undefined ? def : converted; +} diff --git a/src/Helpers/Format.ts b/src/Helpers/Format.ts new file mode 100644 index 0000000..0282ef8 --- /dev/null +++ b/src/Helpers/Format.ts @@ -0,0 +1,6 @@ +import * as dateFormat from 'dateformat'; + +export function formatDate(ts: number, format: string = 'HH:MM:ss') { + const d = new Date(ts * 1000); + return dateFormat(d, format); +} diff --git a/src/Helpers/Identity.ts b/src/Helpers/Identity.ts new file mode 100644 index 0000000..ebecaf4 --- /dev/null +++ b/src/Helpers/Identity.ts @@ -0,0 +1,15 @@ +const ALPHABET = 'abcdefghijklmnopqrstuvwxyz1234567890'; +const ALPHABET_LENGTH = ALPHABET.length - 1; + +function generateId(count: number): string { + let str = ''; + for (let i = 0; i < count; ++i) { + let symbolIndex = Math.floor(Math.random() * ALPHABET_LENGTH); + str += ALPHABET[symbolIndex]; + } + return str; +} + +export function uniqId(prefix: string = 'id'): string { + return prefix + generateId(6); +} diff --git a/src/Helpers/Random.ts b/src/Helpers/Random.ts new file mode 100644 index 0000000..ec0e6af --- /dev/null +++ b/src/Helpers/Random.ts @@ -0,0 +1,10 @@ +export function randomInRange(from: number, to: number): number { + const delta = to - from; + const variation = Math.random() * delta; + return Math.floor(from + variation); +} + +export function around(value: number, koeff: number): number { + const delta = Math.floor(value * koeff); + return randomInRange(value - delta, value + delta); +} diff --git a/src/Helpers/Time.ts b/src/Helpers/Time.ts new file mode 100644 index 0000000..aa2960c --- /dev/null +++ b/src/Helpers/Time.ts @@ -0,0 +1,19 @@ +import { around, randomInRange } from './Random'; + +export function sleep(ms: number) { + return new Promise(resolve => setTimeout(resolve, ms)); +} + +export async function sleepMicro() { + const timeInMs = randomInRange(1500, 2500); + return await sleep(timeInMs); +} + +export function timestamp(): number { + return Math.floor(Date.now() / 1000); +} + +export function aroundMinutes(minutes: number) { + const seconds = minutes * 60; + return around(seconds, 0.1); +} diff --git a/src/Logger.ts b/src/Logger.ts index 69e6cc8..cb988c9 100644 --- a/src/Logger.ts +++ b/src/Logger.ts @@ -1,4 +1,4 @@ -import { timestamp } from './utils'; +import { timestamp } from './Helpers/Time'; export interface Logger { info(...args: any[]): void; diff --git a/src/ModeDetector.ts b/src/ModeDetector.ts index d94e1a9..67ec5c8 100644 --- a/src/ModeDetector.ts +++ b/src/ModeDetector.ts @@ -1,4 +1,4 @@ -import { parseLocation } from './utils'; +import { parseLocation } from './Helpers/Browser'; export enum ManagementMode { Blank = 'blank', diff --git a/src/Page/BuildingPage/BuildingPage.ts b/src/Page/BuildingPage/BuildingPage.ts index 76d3548..71f0fd7 100644 --- a/src/Page/BuildingPage/BuildingPage.ts +++ b/src/Page/BuildingPage/BuildingPage.ts @@ -1,6 +1,7 @@ import { GrabError } from '../../Errors'; -import { getNumber, trimPrefix, uniqId } from '../../utils'; import { Resources } from '../../Core/Resources'; +import { getNumber, trimPrefix } from '../../Helpers/Convert'; +import { uniqId } from '../../Helpers/Identity'; export function clickBuildButton(typeId: number) { const section = jQuery(`#contract_building${typeId}`); diff --git a/src/Page/BuildingPage/ForgePage.ts b/src/Page/BuildingPage/ForgePage.ts index 604b804..aeab42c 100644 --- a/src/Page/BuildingPage/ForgePage.ts +++ b/src/Page/BuildingPage/ForgePage.ts @@ -1,7 +1,8 @@ -import { elClassId, getNumber, uniqId } from '../../utils'; import { Resources } from '../../Core/Resources'; import { grabResourcesFromList } from './BuildingPage'; import { GrabError } from '../../Errors'; +import { elClassId, getNumber } from '../../Helpers/Convert'; +import { uniqId } from '../../Helpers/Identity'; interface ResearchClickHandler { (resources: Resources, unitId: number): void; diff --git a/src/Page/BuildingPage/GuildHallPage.ts b/src/Page/BuildingPage/GuildHallPage.ts index 51e4e9d..99e5540 100644 --- a/src/Page/BuildingPage/GuildHallPage.ts +++ b/src/Page/BuildingPage/GuildHallPage.ts @@ -1,7 +1,8 @@ -import { getNumber, uniqId } from '../../utils'; import { Resources } from '../../Core/Resources'; import { grabResourcesFromList } from './BuildingPage'; import { GrabError } from '../../Errors'; +import { getNumber } from '../../Helpers/Convert'; +import { uniqId } from '../../Helpers/Identity'; interface CelebrationClickHandler { (resources: Resources, id: number): void; diff --git a/src/Page/BuildingPage/MarketPage.ts b/src/Page/BuildingPage/MarketPage.ts index ba5ec3f..e742784 100644 --- a/src/Page/BuildingPage/MarketPage.ts +++ b/src/Page/BuildingPage/MarketPage.ts @@ -1,8 +1,9 @@ -import { getNumber, uniqId } from '../../utils'; import { Resources, ResourcesInterface } from '../../Core/Resources'; import { Coordinates } from '../../Core/Village'; import { IncomingMerchant, MerchantsInfo } from '../../Core/Market'; import { grabResourcesFromList } from './BuildingPage'; +import { getNumber } from '../../Helpers/Convert'; +import { uniqId } from '../../Helpers/Identity'; interface SendResourcesClickHandler { (resources: Resources, crd: Coordinates): void; diff --git a/src/Page/BuildingPage/TrooperPage.ts b/src/Page/BuildingPage/TrooperPage.ts index 44dfb34..d9efe7b 100644 --- a/src/Page/BuildingPage/TrooperPage.ts +++ b/src/Page/BuildingPage/TrooperPage.ts @@ -1,7 +1,8 @@ import { Resources } from '../../Core/Resources'; import { GrabError } from '../../Errors'; -import { elClassId, getNumber, uniqId } from '../../utils'; import { grabResourcesFromList } from './BuildingPage'; +import { elClassId, getNumber } from '../../Helpers/Convert'; +import { uniqId } from '../../Helpers/Identity'; export function createTrainTroopButtons( onClickHandler: (troopId: number, resources: Resources, count: number) => void diff --git a/src/Page/BuildingPageController.ts b/src/Page/BuildingPageController.ts index f52d310..6d4913c 100644 --- a/src/Page/BuildingPageController.ts +++ b/src/Page/BuildingPageController.ts @@ -1,4 +1,3 @@ -import { notify } from '../utils'; import { UpgradeBuildingTask } from '../Task/UpgradeBuildingTask'; import { Scheduler } from '../Scheduler'; import { TrainTroopTask } from '../Task/TrainTroopTask'; @@ -23,6 +22,7 @@ import { ForgeImprovementTask } from '../Task/ForgeImprovementTask'; import { createCelebrationButtons } from './BuildingPage/GuildHallPage'; import { CelebrationTask } from '../Task/CelebrationTask'; import { VillageController } from '../VillageController'; +import { notify } from '../Helpers/Browser'; export class BuildingPageController { private scheduler: Scheduler; diff --git a/src/Page/HeroPage.ts b/src/Page/HeroPage.ts index 60d6e04..66085ae 100644 --- a/src/Page/HeroPage.ts +++ b/src/Page/HeroPage.ts @@ -1,7 +1,7 @@ import { GrabError } from '../Errors'; -import { getNumber } from '../utils'; import { ResourceMapping, ResourceType } from '../Core/ResourceType'; import { HeroAllResources, HeroAttributes, HeroResourceType } from '../Core/Hero'; +import { getNumber } from '../Helpers/Convert'; export function grabHeroAttributes(): HeroAttributes { const healthElement = jQuery('#attributes .attribute.health .powervalue .value'); diff --git a/src/Page/PageDetector.ts b/src/Page/PageDetector.ts index c5558cb..e05d7f3 100644 --- a/src/Page/PageDetector.ts +++ b/src/Page/PageDetector.ts @@ -1,5 +1,6 @@ -import { elClassId, getNumber, parseLocation } from '../utils'; import { FORGE_ID, GUILD_HALL_ID, MARKET_ID } from '../Core/Buildings'; +import { elClassId, getNumber } from '../Helpers/Convert'; +import { parseLocation } from '../Helpers/Browser'; export interface BuildingPageAttributes { buildTypeId: number; diff --git a/src/Page/ResourcesBlock.ts b/src/Page/ResourcesBlock.ts index 7a0eef1..7648208 100644 --- a/src/Page/ResourcesBlock.ts +++ b/src/Page/ResourcesBlock.ts @@ -1,8 +1,8 @@ import { GrabError } from '../Errors'; -import { getNumber } from '../utils'; import { Resources } from '../Core/Resources'; import { ResourceType } from '../Core/ResourceType'; import { ResourceStorage } from '../Core/ResourceStorage'; +import { getNumber } from '../Helpers/Convert'; export function grabVillageResources(): Resources { const lumber = grabResource(ResourceType.Lumber); diff --git a/src/Page/SlotBlock.ts b/src/Page/SlotBlock.ts index e5331d0..d428af9 100644 --- a/src/Page/SlotBlock.ts +++ b/src/Page/SlotBlock.ts @@ -1,6 +1,6 @@ -import { elClassId, getNumber } from '../utils'; import { numberToResourceType } from '../Core/ResourceType'; import { BuildingSlot, ResourceSlot } from '../Core/Slot'; +import { elClassId, getNumber } from '../Helpers/Convert'; interface SlotElement { el: HTMLElement; diff --git a/src/Page/VillageBlock.ts b/src/Page/VillageBlock.ts index b1c00e3..01feb9e 100644 --- a/src/Page/VillageBlock.ts +++ b/src/Page/VillageBlock.ts @@ -1,8 +1,9 @@ import { GrabError } from '../Errors'; -import { getNumber, parseLocation } from '../utils'; import { Resources } from '../Core/Resources'; import { Coordinates, Village, VillageList } from '../Core/Village'; import { BuildingQueueInfo } from '../Core/BuildingQueueInfo'; +import { getNumber } from '../Helpers/Convert'; +import { parseLocation } from '../Helpers/Browser'; function getVillageListItems() { const $elements = jQuery('#sidebarBoxVillagelist ul li a'); diff --git a/src/Queue/TaskProvider.ts b/src/Queue/TaskProvider.ts index b9c74cc..ae65021 100644 --- a/src/Queue/TaskProvider.ts +++ b/src/Queue/TaskProvider.ts @@ -1,8 +1,8 @@ import { Args } from './Args'; -import { uniqId } from '../utils'; import { ResourcesInterface } from '../Core/Resources'; import { ProductionQueue } from '../Core/ProductionQueue'; import { getProductionQueue } from '../Task/TaskMap'; +import { uniqId } from '../Helpers/Identity'; export type TaskId = string; diff --git a/src/Scheduler.ts b/src/Scheduler.ts index f88b7d7..3250d38 100644 --- a/src/Scheduler.ts +++ b/src/Scheduler.ts @@ -1,4 +1,3 @@ -import { around, timestamp } from './utils'; import { TaskQueue } from './Queue/TaskQueue'; import { BalanceHeroResourcesTask } from './Task/BalanceHeroResourcesTask'; import { Logger } from './Logger'; @@ -12,6 +11,8 @@ import { VillageRepositoryInterface } from './VillageRepository'; import { VillageFactory } from './VillageFactory'; import { RunVillageProductionTask } from './Task/RunVillageProductionTask'; import { isProductionTask } from './Task/TaskMap'; +import { around } from './Helpers/Random'; +import { timestamp } from './Helpers/Time'; interface NextExecution { task?: Task; diff --git a/src/Statistics.ts b/src/Statistics.ts index 2626d02..a820189 100644 --- a/src/Statistics.ts +++ b/src/Statistics.ts @@ -1,4 +1,4 @@ -import * as dateFormat from 'dateformat'; +import { formatDate } from './Helpers/Format'; const KEY_FORMAT = 'yyyy-mm-dd-HH'; const KEEP_RECORD_COUNT = 24; @@ -23,7 +23,7 @@ export class Statistics { incrementAction(ts: number): void { const stat = this.storage.getActionStatistics(); - const key = dateFormat(ts * 1000, KEY_FORMAT); + const key = formatDate(ts, KEY_FORMAT); stat[key] = (stat[key] || 0) + 1; this.trimStatistics(stat); this.storage.setActionStatistics(stat); diff --git a/src/Storage/VillageStorage.ts b/src/Storage/VillageStorage.ts index 62ce431..aeef924 100644 --- a/src/Storage/VillageStorage.ts +++ b/src/Storage/VillageStorage.ts @@ -4,7 +4,6 @@ import { ResourceStorage } from '../Core/ResourceStorage'; import { IncomingMerchant, MerchantsInfo } from '../Core/Market'; import { VillageSettings, VillageSettingsDefaults } from '../Core/Village'; import { ProductionQueue } from '../Core/ProductionQueue'; -import { getNumber } from '../utils'; import { Task, uniqTaskId } from '../Queue/TaskProvider'; import { BuildingSlot, @@ -12,6 +11,7 @@ import { ResourceSlot, ResourceSlotDefaults, } from '../Core/Slot'; +import { getNumber } from '../Helpers/Convert'; const RESOURCES_KEY = 'resources'; const CAPACITY_KEY = 'capacity'; diff --git a/src/TaskQueueRenderer.ts b/src/TaskQueueRenderer.ts index e4e9f02..f39d742 100644 --- a/src/TaskQueueRenderer.ts +++ b/src/TaskQueueRenderer.ts @@ -1,14 +1,9 @@ -import { uniqId } from './utils'; -import * as dateFormat from 'dateformat'; import { ImmutableTaskList } from './Queue/TaskProvider'; +import { uniqId } from './Helpers/Identity'; +import { formatDate } from './Helpers/Format'; const ID = uniqId(); -function formatDate(ts: number) { - const d = new Date(ts * 1000); - return dateFormat(d, 'HH:MM:ss'); -} - export class TaskQueueRenderer { render(tasks: ImmutableTaskList) { const ul = jQuery('<ul></ul>') diff --git a/src/VillageController.ts b/src/VillageController.ts index ae1e719..9308b09 100644 --- a/src/VillageController.ts +++ b/src/VillageController.ts @@ -9,7 +9,7 @@ import { ReceiveResourcesMode } from './Core/Village'; import { ResourceType } from './Core/ResourceType'; import { UpgradeBuildingTask } from './Task/UpgradeBuildingTask'; import { GARNER_ID, WAREHOUSE_ID } from './Core/Buildings'; -import { first } from './utils'; +import { first } from './Helpers/Collection'; export class VillageController { private readonly villageId: number; diff --git a/src/VillageState.ts b/src/VillageState.ts index 896e4c7..2584050 100644 --- a/src/VillageState.ts +++ b/src/VillageState.ts @@ -6,10 +6,10 @@ import { VillageRepositoryInterface } from './VillageRepository'; import { VillageNotFound } from './Errors'; import { OrderedProductionQueues, ProductionQueue } from './Core/ProductionQueue'; import { isInQueue, TaskCore, TaskId } from './Queue/TaskProvider'; -import { timestamp } from './utils'; import { VillageTaskCollection } from './VillageTaskCollection'; import { TrainTroopTask } from './Task/TrainTroopTask'; import { Args } from './Queue/Args'; +import { timestamp } from './Helpers/Time'; export interface TaskState { id: TaskId; diff --git a/src/VillageTaskCollection.ts b/src/VillageTaskCollection.ts index ea6b4bd..ceabc6a 100644 --- a/src/VillageTaskCollection.ts +++ b/src/VillageTaskCollection.ts @@ -1,12 +1,12 @@ import { VillageStorage } from './Storage/VillageStorage'; import { Task, TaskId, uniqTaskId, withResources, withTime } from './Queue/TaskProvider'; import { Args } from './Queue/Args'; -import { timestamp } from './utils'; import { Resources } from './Core/Resources'; import { ContractAttributes, ContractType } from './Core/Contract'; import { UpgradeBuildingTask } from './Task/UpgradeBuildingTask'; import { ForgeImprovementTask } from './Task/ForgeImprovementTask'; import { isProductionTask } from './Task/TaskMap'; +import { timestamp } from './Helpers/Time'; export class VillageTaskCollection { private readonly storage: VillageStorage; diff --git a/src/utils.ts b/src/utils.ts deleted file mode 100644 index 96cfc24..0000000 --- a/src/utils.ts +++ /dev/null @@ -1,112 +0,0 @@ -import * as URLParse from 'url-parse'; -import * as _ from 'underscore'; - -export function sleep(ms: number) { - return new Promise(resolve => setTimeout(resolve, ms)); -} - -export function randomInRange(from: number, to: number): number { - const delta = to - from; - const variation = Math.random() * delta; - return Math.floor(from + variation); -} - -export function around(value: number, koeff: number): number { - const delta = Math.floor(value * koeff); - return randomInRange(value - delta, value + delta); -} - -export async function sleepMicro() { - const timeInMs = randomInRange(1500, 2500); - return await sleep(timeInMs); -} - -export function aroundMinutes(minutes: number) { - const seconds = minutes * 60; - return around(seconds, 0.1); -} - -export async function waitForLoad() { - return new Promise(resolve => jQuery(resolve)); -} - -const ALPHABET = 'abcdefghijklmnopqrstuvwxyz1234567890'; -const ALPHABET_LENGTH = ALPHABET.length - 1; - -function generateId(count: number): string { - let str = ''; - for (let i = 0; i < count; ++i) { - let symbolIndex = Math.floor(Math.random() * ALPHABET_LENGTH); - str += ALPHABET[symbolIndex]; - } - return str; -} - -export function uniqId(prefix: string = 'id'): string { - return prefix + generateId(6); -} - -export function timestamp(): number { - return Math.floor(Date.now() / 1000); -} - -export function trimPrefix(text: string, prefix: string): string { - return text.startsWith(prefix) ? text.substr(prefix.length) : text; -} - -export function elClassId(classes: string | undefined, prefix: string): number | undefined { - if (classes === undefined) { - return undefined; - } - let result: number | undefined = undefined; - classes.split(/\s/).forEach(part => { - const match = part.match(new RegExp(prefix + '(\\d+)')); - if (match) { - result = toNumber(match[1]); - } - }); - return result; -} - -export function toNumber(value: any): number | undefined { - const normalized = String(value) - .replace('\u2212', '\u002d') // minus to hyphen-minus - .replace(/[^0-9\u002d]/g, ''); - const converted = Number(normalized); - return isNaN(converted) ? undefined : converted; -} - -export function getNumber(value: any, def: number = 0): number { - const converted = toNumber(value); - return converted === undefined ? def : converted; -} - -export function parseLocation(location?: string | undefined) { - return new URLParse(location || window.location.href, true); -} - -export function notify(msg: string): void { - const n = new Notification(msg); - setTimeout(() => n && n.close(), 4000); -} - -export function markPage(text: string, version: string) { - jQuery('body').append( - '<div style="' + - 'position: absolute; ' + - 'top: 0; left: 0; ' + - 'background-color: white; ' + - 'font-size: 24px; ' + - 'z-index: 9999; ' + - 'padding: 8px 6px; ' + - 'color: black">' + - text + - ' ' + - version + - '</div>' - ); -} - -export function first<T>(items: ReadonlyArray<T>): T | undefined { - return _.first(items); -} diff --git a/tests/UtilsTest.ts b/tests/Helpers/ConvertTest.ts similarity index 94% rename from tests/UtilsTest.ts rename to tests/Helpers/ConvertTest.ts index 966e601..5f62c9a 100644 --- a/tests/UtilsTest.ts +++ b/tests/Helpers/ConvertTest.ts @@ -1,6 +1,6 @@ import { it, describe } from 'mocha'; import { expect } from 'chai'; -import { elClassId, getNumber } from '../src/utils'; +import { elClassId, getNumber } from '../../src/Helpers/Convert'; describe('Utils', function() { describe('getNumber', function() {