Skip to main content

PictModel

PictModel parses a complete PICT-format model — parameters, sub-models, and constraints — into a single object that can directly generate rows. It is exported from a separate entry point so it does not bloat the bundle of consumers who only need make.

import { PictModel } from "covertable/pict";

const model = new PictModel(`
Type: Single, Span, Stripe, Mirror, RAID-5
Size: 10, 100, 500, 1000, 5000, 10000, 40000
Format method: Quick, Slow
File system: FAT, FAT32, NTFS
Cluster size: 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536
Compression: On, Off

IF [File system] = "FAT" THEN [Size] <= 4096;
IF [File system] = "FAT32" THEN [Size] <= 32000;
`);

const rows = model.make();

Constructor

new PictModel(input: string, options?: PictModelOptions)
OptionTypeDefaultDescription
caseInsensitivebooleantrueWhen true (default, matching PICT), constraint comparisons and alias lookups ignore case.
strictbooleanfalseWhen true, the constructor throws PictModelError if any error-severity issue is collected.

The input string is split into three sections:

  1. ParametersName: value1, value2, ...
  2. Sub-models{ A, B, C } @ N
  3. ConstraintsIF [P] = "x" THEN [Q] = "y"; or unconditional [P] <> [Q];

Properties

PropertyTypeDescription
parametersRecord<string, (string | number)[]>Parsed parameter values (canonical form, with aliases removed).
subModelsSubModelType[]Parsed sub-model definitions.
constraints(FilterType | null)[]Parsed constraint filters. null entries indicate parse failure.
negativesMap<string, Set<string | number>>Values prefixed with ~ (invalid / negative-test values) per parameter.
weightsRecord<string, Record<number, number>>Weights extracted from (N) syntax.
issuesPictModelIssue[]All issues collected during parsing.
progressnumberCoverage progress (0 to 1) during generation.
statsControllerStats | nullGeneration statistics (available after make/makeAsync).

Issues

interface PictModelIssue {
severity: "error" | "warning";
source: "factor" | "subModel" | "constraint";
index: number; // 0-based index within the source
line: number; // 1-based line number in the original input
message: string;
}
const model = new PictModel(`
A: 1, 2
Empty:
`);
model.issues;
// [{ severity: "error", source: "factor", index: 1, line: 3,
// message: 'No values for parameter "Empty"' }]

Methods

MethodDescription
filter(row)Returns true if the row satisfies all constraints and has at most one invalid value.
make(options?)Generates rows with the model's parameters, constraints, sub-models, and weights. Accepts the same options as the top-level make.
makeAsync(options?)Generator version of make.

Supported PICT Syntax

FeatureExampleNotes
ParameterType: Single, Span, StripeBasic parameter declaration.
Comment# this is a commentLines starting with # are skipped.
Quoted stringsMsg: "hello, world"Required for values containing commas.
Parameter referenceB: <A>, extraExpands to all of parameter A's values.
AliasesOS: Windows | Win, LinuxFirst value is canonical. Aliases work in constraints.
Invalid valuesType: Valid, ~InvalidNegative-test value. At most one per row. Output includes ~ prefix.
WeightsBrowser: Chrome (10), FirefoxBiases value selection during completion.
Sub-models{ A, B, C } @ 3Different N-wise strength for listed parameters.
ConditionalIF [A] = 1 THEN [B] = 2;Standard PICT-style conditional constraints.
Unconditional[A] <> [B];Always-applied invariants.
Comparisons=, <>, >, <, >=, <=, IN, LIKEAll standard PICT operators.
LogicalAND, OR, NOTWith parentheses for grouping.

Invalid Values (~)

When a value is prefixed with ~, it is treated as a value that should appear in tests only one at a time. PictModel automatically rejects rows containing two or more invalid values. The ~ prefix is preserved in output rows.

const model = new PictModel(`
Age: 20, 30, ~-1, ~999
Country: Japan, USA, ~"Mars"
`);

const rows = model.make();
// { Age: 20, Country: "Japan" } — both valid
// { Age: "~-1", Country: "Japan" } — Age is invalid, Country is valid
// { Age: 20, Country: "~Mars" } — Age is valid, Country is invalid
// { Age: "~-1", Country: "~Mars" } — REJECTED (two invalid values)

Aliases

Aliases provide alternative names for the same value. The first name is canonical (appears in output), while alternates are accepted in constraints.

const model = new PictModel(`
OS: "Windows 10" | Win10, "Mac OS" | Mac, Linux
Result: pass, fail

IF [OS] IN {"Win10", "Mac"} THEN [Result] = "pass";
`);

weightsByValue

A helper that converts a value-keyed weight map into the index-keyed form expected by weights.

import { make } from "covertable";
import { weightsByValue } from "covertable/pict";

const factors = {
Browser: ["Chrome", "Firefox", "Safari"],
};

make(factors, {
weights: weightsByValue(factors, {
Browser: { Chrome: 10, Safari: 5 },
}),
// equivalent to: weights: { Browser: { 0: 10, 2: 5 } }
});
Try it interactively

Try the Compatible PICT tool to experiment with the constraint syntax in your browser.