Split utils functions into set of helper modules

This commit is contained in:
Anton Vakhrushev 2020-07-18 17:25:47 +03:00
parent d57d8c4942
commit dfc7d48fd4
48 changed files with 175 additions and 163 deletions

View File

@ -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 } = {};

View File

@ -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 {

View File

@ -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 {

View File

@ -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 {

View File

@ -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 {

View File

@ -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 },

View File

@ -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 {

View File

@ -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 {

View File

@ -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 {

View File

@ -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);

View File

@ -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);

View File

@ -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',

View File

@ -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;

View File

@ -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;

View File

@ -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 {

View File

@ -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 {

View File

@ -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 {

View File

@ -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 {

31
src/Helpers/Browser.ts Normal file
View File

@ -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>'
);
}

View File

@ -0,0 +1,5 @@
import * as _ from 'underscore';
export function first<T>(items: ReadonlyArray<T>): T | undefined {
return _.first(items);
}

30
src/Helpers/Convert.ts Normal file
View File

@ -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;
}

6
src/Helpers/Format.ts Normal file
View File

@ -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);
}

15
src/Helpers/Identity.ts Normal file
View File

@ -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);
}

10
src/Helpers/Random.ts Normal file
View File

@ -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);
}

19
src/Helpers/Time.ts Normal file
View File

@ -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);
}

View File

@ -1,4 +1,4 @@
import { timestamp } from './utils';
import { timestamp } from './Helpers/Time';
export interface Logger {
info(...args: any[]): void;

View File

@ -1,4 +1,4 @@
import { parseLocation } from './utils';
import { parseLocation } from './Helpers/Browser';
export enum ManagementMode {
Blank = 'blank',

View File

@ -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}`);

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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');

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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');

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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';

View File

@ -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>')

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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);
}

View File

@ -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() {