npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

weighted-randoms

v1.3.3

Published

A simple lightweight class designed for working with weighted randoms

Downloads

5

Readme

weighted-randoms

Overview

Weighted randoms solves a problem that has been solved, resolved and further iterated on by me several times over. The primary purpose of the package is to take my latest iteration of choosing a random item easily and, in some cases, choose that value in a manner that is somewhat uneven as compared to the other options being selected from.

Principals

Items in the selection set are all assigned a weight. By default this weight is the integer 1 but can be any Number. Floating point numbers are also valid and mixing is ok as well. The greater the weight, the more likely the item will be chosen.

The library accomplishes this without wasting memory with large gaps and is flexible enough to be used with varying types of data sets.

TODO

1.2.x and previous versions

  • [ ] Explain new Random()
  • [ ] Explain new Random().generate()
  • [ ] Explain new Random().one()
  • [ ] Explain new Random().some()
  • [ ] Explain new Random().range()
  • [ ] Explain new Random().add()
  • [ ] Explain new Random().addRange()
  • [ ] Explain new Random().size {get}
  • [ ] Explain new Random().standardWeight {get, set}
  • [ ] Explain new Random().reweighStandardItems()
  • [X] Explain Random.one()
  • [ ] Explain Random.one() in detail
  • [ ] Explain Random.some()
  • [X] Explain Random.range()
  • [ ] Explain Random.range() in detail
  • [ ] Explain Random.keys()
  • [ ] Explain Random.values()
  • [ ] Explain Random.ofWeight()
  • [ ] Explain Random.roll()
  • [ ] Explain Random.from()
  • [ ] Explain Random.item()
  • [ ] Explain new Item()

1.3.x

  • [ ] Explain Random.fromCSVFile()

New Features

As of 1.2.x, the ability to chain a random item selection from subsequent instances of Random has been added. This is done by adding a .next property to an item in a Random instance list. If .next is truthy and an instance of Random then a loop is created where .next.one() is called until the resulting value is no longer an instance of Random or is falsey.

Additionally, a .postProcess() function is supported on each Item instance. If present and a function, then the final chosen value will be passed as a parameter. The expectation is that the returned value will a potentially modified version of the final chosen value.

Lastly, in 1.2.x, a shell script called repl.sh is included that creates a node repl with all the imports already ready for testing. This made my life easier and makes it easier to play with weighted randoms.

Installation

npm install --save weighted-randoms

Usage

import { Random } from 'weighted-randoms'

Random.one('apple', 'orange', 'pear') // 'orange'
Random.range(1,10).some()             // [1,5,10]
Random.one(1, [3, 5], 7)              // 3 

While these examples are simple and seem to fit the bill, a more complex example is provided. This example can be played with directly through the use of the repl.js script or they can be directly require()'d or import'ed. There is a png in this repo named "Magic Items Table.png". This was taken from an early 1974 copy of Dungeons & Dragons Basic Rules. The png shows the data in question that is to be converted into a random choice with weighted values and sub-table values. There are comments in the code to explain how special cases work, but these come from the newly provided next and postProcess properties.

Let's take a look

$ ./repl.sh
> MagicItemsTable.some(5)
[
  'Sword +1, +2 against Lycanthropes',
  'Potion of Levitation',
  'Protection from Lycanthropes',
  'Protection from Undead',
  'Gauntlets of Ogre Power'
]
>

This can also be done with npm run repl which gives the following results:

$ npm run repl

> [email protected] repl
> node ./repl.sh

> MagicItemsTable.some(5)
[
  'Axe +1',
  'Sword +1, +2 against Lycanthropes',
  'Protection from Lycanthropes',
  'Potion of Invisibility',
  'Spell scroll: 3 magic-user/elf spells (any)'
]
>

So what's going on here? The file DnDBasicRulesMagic.js has all its exports placed into the global scope inside the repl created when ./repl.sh is executed. If trying to run this does not work in your cloned repo, try adding the command node in front of it (i.e. node ./repl.sh).

Inside the DnDBasicRulesMagic.js file there are 8 exported values

[
  'MagicItemsTable',
  'MiscellaneousMagicTable',
  'PotionsTable',
  'RingsTable',
  'ScrollsTable',
  'SwordsTable',
  'WandsStavesRodsTable',
  'WeaponsArmorTable'
]

Each of these exports is an instance of Random with items predefined within. Each item in the top level MagicItemsTable Random instance has a .next property. This property in turn has one of the other seven exported Random instances as a value.

If an item is chosen that has a .next value, it has its .one() function invoked to get the next subsequent item. This process continues until the final value is no longer an instance of Random.

Once a final item is chosen, if the original item had a .postProcess() function property, it is invoked with the chosen item value. The .postProcess() function property takes the chosen item and returns an item; usually a modified version of the previously chosen item.

In the DnDBasicRulesMagic.js example, values from the "Rings" and "Potions" tables list effects. It would be unclear if it were a Potion or a Ring unless we prepend the text "Ring of " or "Potion of ", respectively. So a .postProcess() function is added to the top level choice for Rings and Potions that prepends the text to whatever item was eventually selected, solving this problem.

CSV Files

In 1.3.x the ability to read tables, including nested tables, from CSV files has been added. The sample files, an equivalent to the purely JS created version, is available in the repl as csvSample. The csv files themselves are located in the src/CSV. An absolute path is required for the parameter to Random.fromCSVFile(), however, if COLS_NESTED or COLS_NESTED_OBJ are supplied the paths in those columns can be relative to the first file. This is how the sample is setup to be.

An example of the first file mentioned above looks like this:

20,"Sword","./Swords.csv"
20,"Weapon/Armor","./WeaponArmor.csv"
25,"Potion","./Potions.csv"
20,"Scroll","./Scrolls.csv"
5,"Ring","./Rings.csv"
5,"Wand/Staff/Rod","./WandsStavesRods.csv"
5,"Miscellaneous Magic","./MiscellaneousMagic.csv"

An instance of Random is created and during this creation, the process will recursively traverse the specified files and build .next links to subsequent items.