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

scrimshaw

v1.0.0

Published

Magical blueprints for procedural generation of content.

Downloads

2

Readme

scrimshaw

Magical blueprints for procedural generation of content.

Installing

To install, use npm:

npm install scrimshaw

Alternately, you can find the source on Github.

Getting Started

scrimshaw provides the Scrimshaw object. You can require it directly:

var Scrimshaw = require('scrimshaw');

Reference

scrimshaw provides a simple interface that is designed to be extensible. In fact, by itself, the base Scrimshaw won't do very much at all.

Scrimshaw

A Scrimshaw is a plan for building a procedural data object. You define a Scrimshaw "subclass" with static and dynamic members, a list of attributes to export, and an output type to fill with the results.

var Scrimshaw = require('scrimshaw');

// We'll use the Ivoire framework for our randomization,
// but you could use anything:
var Ivoire = require('ivoire');

// A simple NPC
var NPC = function NPC() {};
NPC.prototype.say = function (message) {
  console.log(this.name + " says " + message);
}

var NPCScrimshaw = Ivoire.Scrimshaw.extend({
  export_attributes: [
    'name',
    'sex',
    'job'
  ],

  // Instead of the default vanilla object, make an NPC object. If
  // make_type is a function, it must return the object it is making.
  make_type: function () { return new NPC() },

  // This Ivoire instance isn't in `exported_attributes`, so it won't be copied
  // to the generated object.
  ivoire: new Ivoire(),

  // Static attributes are simple values
  job: "worker",

  // Dynamic attributes are functions
  sex: function () {
    return this.ivoire.pick(['male', 'female'])
  },

  name: function () {

    // We use the special `#get()` function to access other attributes. This
    // ensures that the value we receive will be constant for each instance of the
    // scrimshaw.
    var sex = this.get('sex');

    if (sex == 'male') {
      return this.ivoire.pick(['Joseph', 'Samuel']);
    } else {
      return this.ivoire.pick(['Josie', 'Samantha']);
    }
  }
});

// Pass in an ivoire instance to the generator:
var npc = NPCScrimshaw.generate();

// Or don't, which will give a randomly-seeded NPC:
npc = NPCScrimshaw.generate();
console.log(npc.name, npc.sex);
npc.say("Hello, world!");


// We can extend an existing scrimshaw to make new derived scrimshaws:
var PoliceNPCScrimshaw = NPCScrimshaw.extend({
  job: "police"
});

var police_npc = PoliceNPCScrimshaw.generate();
console.log(npc.name, npc.sex);
police_npc.say("Hello, citizen!");

The base Scrimshaw provides a minimal interface and a pattern for extension. You create a scrimshaw by extending another scrimshaw, or the base Scrimshaw. You specify which "attributes" to export (the export_attributes array) and the type to export the attributes to (make_type, defaulting to {}). Then you define the attributes as static members or dynamic functions. Dynamic attributes can depend on other attributes using the #get() method.

#create()

Syntax

scrimshaw.create()

Usage

#create() will create a new copy of the scrimshaw in question, with a fresh cache.

#export()

Syntax

scrimshaw.export([overrides])

Usage

#export() will evaluate all #exported_attributes and export them to the result of #make_type. #export() is idempotent: because #get() caches the results of dynamic attributes, subsequent calls to #export() should produce identical results.

If an overrides object is provided to #export(), the attributes will be exported from an extended version of the scrimshaw instead. This allows dependent dynamic attributes to be affected by the overrides.

#export(overrides) should be idempotent for subsequent calls with identical overrides.

#extend()

Syntax

scrimshaw.extend(body)

Usage

To create a new scrimshaw, extend an existing one, or the base Scrimshaw object, providing attributes and overrides:

var NPCScrimshaw = Scrimshaw.extend({
  export_attributes: [
    'job'
  ],
  job: "worker"
});

var PoliceNPCScrimshaw = NPCScrimshaw.extend({
  job: "police"
});

var SecretaryNPCScrimshaw = NPCScrimshaw.extend({
  job: "secretary"
})

#generate()

Syntax

scrimshaw.generate([overrides])

Usage

Generate a new make_type, exporting attributes from a new scrimshaw with a fresh cache, and ignoring any existing cache on this scrimshaw.

var RandomScrimshaw = Scrimshaw.extend({
  export_attributes: [
    'foo'
  ],
  foo: function () {
    return Math.random();
  }
});

// Subsequent calls to `#generate()` produce fresh instances.
var bar = RandomScrimshaw.generate();
var baz = RandomScrimshaw.generate();
bar.foo != baz.foo;

If overrides are provided to #generate(), the scrimshaw will be extended with the overrides before exporting its attributes. This allows us to specify, for instance, a custom randomizer object at generation time:

var RandomScrimshaw = Scrimshaw.extend({
  export_attributes: [
    'foo'
  ],

  foo: function () {
    // Note: `ivoire` will be undefined on the unmodified scrimshaw.
    ivoire = this.get('ivoire');
    return ivoire.natural();
  }
});

// Subsequent calls to `#generate()` produce fresh instances.  Supplying
// the `ivoire` object in the overrides satisfies the dependency in `foo`.
var bar = RandomScrimshaw.generate({ivoire: new Ivoire({seed: 42})});
var baz = RandomScrimshaw.generate({ivoire: new Ivoire({seed: 43})});

// If the same seed were used for both calls, the resulting instances would
// have been the same:
bar.foo != baz.foo;

#get(name)

Syntax

scrimshaw.get(name)

Usage

To access a static or dynamic attribute on a scrimshaw, always use #get(). This will work with either a static or dynamic attribute, and will ensure that a dynamic variable remains constant for the scrimshaw instance.

var RandomScrimshaw = Scrimshaw.extend({
  export_attributes: [
    'foo'
  ],
  foo: function () {
    return Math.random();
  }
});

Acknowledgements

The idea for Scrimshaw comes from the "Blueprints" concept developed by Sean Howard, though his ideas are much richer than currently implemented in scrimshaw. I have also developed a similar library for Python, called blueprint.