Comparing version 1.0.0 to 1.1.0
@@ -1,52 +0,38 @@ | ||
/** | ||
* random operations | ||
*/ | ||
declare class Random { | ||
private value; | ||
constructor(value?: number); | ||
interface Random { | ||
id(length?: number, radix?: number): string; | ||
bool(probability: number): boolean; | ||
/** | ||
* random real | ||
* @param start start number | ||
* @param end end number | ||
* @returns a random real in the interval [start, end) | ||
* @param lower lower bound (inclusive) | ||
* @param upper upper bound (exclusive) | ||
* @returns a random real in the interval [lower, upper) | ||
*/ | ||
real(end: number): number; | ||
real(start: number, end: number): number; | ||
real(upper: number): number; | ||
real(lower: number, upper: number): number; | ||
/** | ||
* random integer | ||
* @param start start number | ||
* @param end end number | ||
* @returns a random integer in the interval [start, end) | ||
* @param lower lower bound (inclusive) | ||
* @param upper upper bound (exclusive) | ||
* @returns a random integer in the interval [lower, upper) | ||
*/ | ||
int(end: number): number; | ||
int(start: number, end: number): number; | ||
int(upper: number): number; | ||
int(lower: number, upper: number): number; | ||
splice<T>(source: T[]): T; | ||
pick<T>(source: readonly T[]): T; | ||
splice<T>(source: T[]): T; | ||
pick<T>(source: readonly T[], count: number): T[]; | ||
shuffle<T>(source: readonly T[]): T[]; | ||
weightedPick<T extends string>(weights: Readonly<Record<T, number>>): T; | ||
} | ||
declare namespace Random { | ||
function id(length?: number, radix?: number): string; | ||
/** | ||
* random real | ||
* @param start start number | ||
* @param end end number | ||
* @returns a random real in the interval [start, end) | ||
*/ | ||
function real(end: number): number; | ||
function real(start: number, end: number): number; | ||
/** | ||
* random integer | ||
* @param start start number | ||
* @param end end number | ||
* @returns a random integer in the interval [start, end) | ||
*/ | ||
function int(end: number): number; | ||
function int(start: number, end: number): number; | ||
function pick<T>(source: readonly T[]): T; | ||
function shuffle<T>(source: readonly T[]): T[]; | ||
function multiPick<T>(source: T[], count: number): T[]; | ||
function weightedPick<T extends string>(weights: Readonly<Record<T, number>>): T; | ||
function bool(probability: number): boolean; | ||
interface Static extends Random { | ||
chars: string; | ||
new (get?: () => number): Random; | ||
} | ||
} | ||
export = Random; | ||
declare class Random { | ||
private get; | ||
static chars: string; | ||
constructor(get?: () => number); | ||
} | ||
declare const _default: Random.Static; | ||
export = _default; |
100
lib/index.js
"use strict"; | ||
/** | ||
* random operations | ||
*/ | ||
class Random { | ||
constructor(value = Math.random()) { | ||
this.value = value; | ||
constructor(get = Math.random) { | ||
this.get = get; | ||
} | ||
id(length = 8, radix = 16) { | ||
let result = ''; | ||
for (let i = 0; i < length; ++i) { | ||
result += Random.chars[Math.floor(Math.random() * radix)]; | ||
} | ||
return result; | ||
} | ||
bool(probability) { | ||
@@ -14,8 +18,8 @@ if (probability >= 1) | ||
return false; | ||
return this.value < probability; | ||
return this.get() < probability; | ||
} | ||
real(...args) { | ||
const start = args.length > 1 ? args[0] : 0; | ||
const end = args[args.length - 1]; | ||
return this.value * (end - start) + start; | ||
const lower = args.length > 1 ? args[0] : 0; | ||
const upper = args[args.length - 1]; | ||
return this.get() * (upper - lower) + lower; | ||
} | ||
@@ -25,11 +29,22 @@ int(...args) { | ||
} | ||
pick(source) { | ||
return source[Math.floor(this.value * source.length)]; | ||
} | ||
splice(source) { | ||
return source.splice(Math.floor(this.value * source.length), 1)[0]; | ||
return source.splice(Math.floor(this.get() * source.length), 1)[0]; | ||
} | ||
pick(source, count) { | ||
if (count === undefined) | ||
return this.pick(source, 1)[0]; | ||
const copy = source.slice(); | ||
const result = []; | ||
count = Math.min(copy.length, count); | ||
for (let i = 0; i < count; i += 1) { | ||
result.push(this.splice(copy)); | ||
} | ||
return result; | ||
} | ||
shuffle(source) { | ||
return this.pick(source, source.length); | ||
} | ||
weightedPick(weights) { | ||
const total = Object.entries(weights).reduce((prev, [, curr]) => prev + curr, 0); | ||
const pointer = this.value * total; | ||
const pointer = this.get() * total; | ||
let counter = 0; | ||
@@ -43,54 +58,7 @@ for (const key in weights) { | ||
} | ||
(function (Random) { | ||
const chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; | ||
function id(length = 8, radix = 16) { | ||
let result = ''; | ||
for (let i = 0; i < length; ++i) { | ||
result += chars[Math.floor(Math.random() * radix)]; | ||
} | ||
return result; | ||
} | ||
Random.id = id; | ||
function real(...args) { | ||
return new Random().real(...args); | ||
} | ||
Random.real = real; | ||
function int(...args) { | ||
return new Random().int(...args); | ||
} | ||
Random.int = int; | ||
function pick(source) { | ||
return new Random().pick(source); | ||
} | ||
Random.pick = pick; | ||
function shuffle(source) { | ||
const clone = source.slice(); | ||
const result = []; | ||
for (let i = source.length; i > 0; --i) { | ||
result.push(new Random().splice(clone)); | ||
} | ||
return result; | ||
} | ||
Random.shuffle = shuffle; | ||
function multiPick(source, count) { | ||
source = source.slice(); | ||
const result = []; | ||
const length = Math.min(source.length, count); | ||
for (let i = 0; i < length; i += 1) { | ||
const index = Math.floor(Math.random() * source.length); | ||
const [item] = source.splice(index, 1); | ||
result.push(item); | ||
} | ||
return result; | ||
} | ||
Random.multiPick = multiPick; | ||
function weightedPick(weights) { | ||
return new Random().weightedPick(weights); | ||
} | ||
Random.weightedPick = weightedPick; | ||
function bool(probability) { | ||
return new Random().bool(probability); | ||
} | ||
Random.bool = bool; | ||
})(Random || (Random = {})); | ||
Random.chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; | ||
const instance = new Random(); | ||
for (const key of ['id', 'bool', 'int', 'real', 'splice', 'pick', 'shuffle', 'weightedPick']) { | ||
Random[key] = instance[key].bind(instance); | ||
} | ||
module.exports = Random; |
{ | ||
"name": "inaba", | ||
"description": "A collection of random utilities", | ||
"version": "1.0.0", | ||
"version": "1.1.0", | ||
"main": "lib/index.js", | ||
@@ -6,0 +6,0 @@ "typings": "lib/index.d.ts", |
@@ -15,3 +15,9 @@ # inaba | ||
Random.int(0, 10) // 5 | ||
Random.bool(0.8) // gets a random boolean | ||
Random.shuffle([5, 1, 4]) // randomly shuffles an array | ||
// use custom random function | ||
const random = new Random(() => Math.random()) | ||
Random.int(0, 10) // gets a random integer | ||
random.pick([1, 2, 3]) // picks a random element from an array | ||
``` | ||
@@ -44,23 +50,16 @@ | ||
### Random.shuffle(array) | ||
### Random.pick(array, count?) | ||
- **array:** `T[]` | ||
- returns: `T[]` | ||
Randomly shuffles an array. | ||
### Random.pick(array) | ||
- **array:** `readonly T[]` | ||
- returns: `T` | ||
- **count:** `number` | ||
- returns: `T | T[]` | ||
Randomly picks an element from an array. | ||
If `count` is not provided, returns a random element from `array`; otherwise returns an array of `count` random elements from `array`. | ||
### Random.multiPick(array, count) | ||
### Random.shuffle(array) | ||
- **array:** `readonly T[]` | ||
- **count:** `number` | ||
- **array:** `T[]` | ||
- returns: `T[]` | ||
Randomly picks `count` elements from an array. | ||
Randomly shuffles an array. It is equivalent to `.pick(array, array.length)`. | ||
@@ -72,2 +71,2 @@ ### Random.weightedPick(weights) | ||
Randomly picks an element from a dict with weights. | ||
Randomly picks a key from a dict, using corresponding value as weight. |
7191
99
70