AIDC Toolkit Help

Utility Package

The utility package provides classes to manipulate integers and strings, independently of any AIDC problem domain. The package has been designed to maximize performance and minimize memory by reducing many of the typical AIDC requirements, such as serial component generation, to on-demand generation using standard JavaScript Iterable, Iterator, and IterableIterator types.

To provide the most flexibility and to handle the most significant demands of the AIDC problem domain, the AIDC Toolkit uses the JavaScript bigint type, with many functions converting from the more primitive number type if provided. This gives applications significant flexibility at a small performance cost inherent in bigint operations.

Integers

Sequencer

Many of AIDC processes can be reduced to a simple statement about sequences:

  • "Give me a million serial numbers for manufacturing."

  • "Generate a handful of GTINs for my new product line."

  • "Label the containers in the shipping area with SSCCs."

Each statement has a quantity and an output. Implicit in them, however, is the requirement that the generated output be unique, not only within itself, but also within any previous outputs generated. A sequencer is simply a utility to generate a sequence of integers given a start value and a count.

Creating and using a sequencer

  1. Create a sequencer with a start value and a count. The count is typically positive, which means that the sequencer runs from the start value up. If negative, the sequencer runs from the start value down.

    // Sequencer starts at 33,000 and will iterate 1,000 times. const sequencer = new Sequencer(33000, 1000);
  2. Use the sequencer.

    • Use it in a for loop.

      for (const value of sequencer) { console.log(value); }
    • Use it as an Iterator.

      let done = false; do { const next = sequencer.next(); if (next.done === undefined || !next.done) { console.log(value); } else { done = true; // Sequencer returns absolute value of count when iterator is exhausted. console.log(`Total generated is ${next.value}`); } } while (!done);
    • Transform it using an Iterator method.

      const sum = Iterator.from(sequencer).reduce((accumulator, value) => accumulator + value, 0);
    • Pass it to a function.

      // Generate sequence of 10-character strings. const stringSequencer = NUMERIC_STRING_CREATOR.create(10, sequencer);

Transformer

A transformer transforms values in a numeric domain to values in a range equal to the domain or to another range defined by a callback function.

There are two types of transformers defined in the AIDC Toolkit: the identity transformer and the encryption transformer. Regardless of the type, before any input value is transformed, it is validated against the domain provided when constructing the transformer; if the input value is less than zero or greater than or equal to the domain, an error is thrown.

The identity transformer simply maps any input value to the same output value.

The encryption transformer maps an input value to an output value resulting from repeated shuffle and xor operations defined by a tweak. In cryptography, a tweak is a value that alters an operation to change or "tweak" the output in a predictable and unique way that is hard to reverse engineer. Normally, a tweak works side by side with a password to generate a cryptographic key to ensure that no two systems can produce the same output from the same input and password; each system defines its own tweak and the password is kept by the user. Because the tweak is applied to every encryption operation, it is inherently less secure (e.g., a system administrator may know the tweak but that's not enough to compromise any user's encryption), but for the purposes of the AIDC Toolkit, it is secure enough.

Suppose that you're manufacturing a product that is valuable enough to be of interest to counterfeiters. To protect the product, you want to generate a unique serial component for each one you put on the market. If anyone submits a warranty claim, the serial component will tell you whether the product is legitimate.

You expect that you will manufacture at most 1,000,000 units of the product before releasing an upgrade, so your serial components are going to be numeric only and 6 digits long. If you generate the serial components in sequence, then generating 10 of them starting from unit 200,000 results in the following: 200000, 200001, 200002, 200003, 200004, 200005, 200006, 200007, 200008, 200009.

// Transformer has a domain of 1,000,000; no tweak means that the identity transformer is used. for (const value of Transformer.get(1000000).forward(new Sequencer(200000, 10))) { console.log(value); }

The sequence is predictable and a counterfeiter can easily guess at valid serial numbers, which will cause problems for distributors and retailers when they see duplicates in the supply chain, problems for your customers who believe they are buying a legitimate product, and problems for you when you can't easily distinguish legitimate from counterfeit.

Using the encryption transformer, you put some space between your serial components, making them 8 digits long, and you set the tweak to some random value. Generating 10 serial components starting from unit 200,000 results in the following: 14608575, 00118914, 14609085, 00250498, 07625339, 85755635, 41179259, 67532896, 02000912, 19087354.

// Transformer has a domain of 100,000,000; tweak means that the encryption transformer is used. for (const value of Transformer.get(100000000, 8675309).forward(new Sequencer(200000, 10))) { console.log(value); }

The sequence is statistically random and a counterfeiter is highly unlikely to guess at valid serial numbers, which will make detection of illegitimate serial numbers significantly easier for all parties.

Sequencer and Transformer

The Transformer class underlies most AIDC Toolkit operations involved in string creation. The forward() method takes either a single bigint value or an Iterable%lt;bigint> of values. This provides maximum flexibility, but it comes at a cost. All inputs are validated prior to transformation, which can add to the system load when transforming a large number of values.

When dealing with Iterable objects, transformers will recognize Sequencer objects and will validate the start value and count at the beginning rather than each value individually as they are transformed. This reduces the number of validations from however many entries there are in Iterable object to two. It also ensures that the client code deals with errors at the very beginning rather than in the middle of its processing.

Single value
Iterable
Sequencer
Not done
Done
Not Sequencer
Not done
Done
Value(s) type
Validate value
Process value
Return result(s)
Iterable type
Validate minimum value
Validate maximum value
For each value
Process value
Next
For each value
Validate value
Process value
Next

Strings

String validation

Validation is a requirement for any application. The AIDC Toolkit provides a simple but extensible validation framework built on two interfaces: StringValidation and StringValidator. The two are related in that an interface extending StringValidation may be passed as a parameter to the validate() method of a class implementing StringValidator to restrict validation further. For example, the CharacterSetValidator implementation accepts a CharacterSetValidation object that can constrain the length and limit the way numeric values are expressed (e.g., exclude zero as the first character).

The StringValidation interface is a placeholder only; it's empty, which, in a structurally typed language like TypeScript, matches any object, so it's up to StringValidator implementations to decide what the implementation type should be.

Validation is straightforward: if a string passed to a validate() method is valid, the method returns; if not, a RangeError is thrown.

Predefined validators

The following validator types are predefined:

Type

Description

Regular expression

Validates a string against a regular expression.

Record

Validates a string by looking it up in a Record object.

Character set

Validates a string by ensuring that each character is within a defined character set, with additional validation parameters optionally constraining the length and limiting the way numeric values are expressed. Predefined character set validators are:

  • Numeric (0-9)

  • Hexadecimal (0-9, A-F)

  • Alphabetic (A-Z)

  • Alphanumeric (0-9, A-Z)

String creation

String creation varies depending on the type of string being created, so there's no single interface that can be implemented. There is a pattern, however:

  • Creation is done via a create() method. If the class can create more than one type of string, it can define additional createNNN() methods as appropriate.

  • The create() (or createNNN()) method is overloaded, with a parameter accepting either a single value to create a single string or multiple values to create multiple strings.

  • If the value to create a string is of type bigint:

Predefined creators

The following creator types are predefined:

Type

Description

Character set

Creates strings by mapping bigint values to fixed length string representations using the character set as the "digits" of the string. Predefined character set creators are:

  • Numeric (0-9)

  • Hexadecimal (0-9, A-F)

  • Alphabetic (A-Z)

  • Alphanumeric (0-9, A-Z)

Last modified: 28 September 2024