Interactive Economics GraphsManagerial economics and game theory, built with kgjs-next.
Gallery Manual Builder Code editor

Spec reference (v0.1)

A complete field-by-field reference for the graph spec, with the correct term for each thing.

How to talk about it

The file is a spec, written as a JSON object. An object is a set of properties. Each property has a name (the key, before the colon) and a value (after it). A value can be a number, a string, a boolean, an array (a list, in square brackets), or another object (nested properties, in curly braces).

So when you see:

"axes": { "x": { "label": "Quantity", "min": 0, "max": 60 } }

you would say: axes is a top-level property; its value is an object with an x property; the value of x is an axis object; and label, min, max are properties of that axis object. To point at one precisely, say "the min of the x-axis."

Two more terms you will use constantly. A value written as a string like "demandIntercept + slope*x" is an expression, evaluated live against the scope (all your params and derived values). And each entry in the objects list is a graph object (or primitive), whose type property picks which kind it is.

Throughout this reference, expr means "a number, or an expression string." point means a two-element array [expr, expr].

Top-level properties

Property Value Required Meaning
version string yes Spec version, currently "0.1".
title string no Drawn as a heading above graphs, games, and trees. Renders $...$ math.
titleSize number no Font size (px) of the title (default 15). Still scaled by fontScale.
fontScale number no Scales all text in the graph at once (1 = default, 1.3 = 30% larger). Good for slides/projection.
graphWidth number no Graph drawing width in px (default 640). Smaller values help the sidebar fit beside the graph.
sidebarWidth number no Sidebar width in px (default 290).
sidebarPosition string no "right" forces the sidebar beside the graph even when space is tight; "bottom" forces it below; omit for automatic (beside when wide, below when narrow).
params array of param no The adjustable variables (become sliders / drag targets).
derived object of name to expr no Values computed from params. See Scope below.
colors object of name to color no Add or override palette color names.
axes axes object one of the five Single-panel graph. Pair with objects.
objects array of graph object with axes The things drawn in the single panel.
panels array of panel one of the five Several stacked graphs instead of axes+objects.
game game object one of the five A normal-form (matrix) game.
tree tree object one of the five An extensive-form game tree.
repeated repeated object one of the five An infinitely repeated 2×2 game (matrix + discounting analysis).
sidebar sidebar object no Sliders and text beside the graph.

You provide exactly one of these five content forms: axes+objects (single panel), panels (multiple panels), game (a matrix game), tree (a game tree), or repeated (a repeated game). params, derived, colors, and sidebar may accompany any of them.

Sizing and layout

Two levels of text sizing, and they compose:

Layout is controlled by graphWidth, sidebarWidth, and sidebarPosition (above). By default the graph and sidebar sit in a row that wraps the sidebar underneath when the container is too narrow (roughly under ~700px for a 640px graph plus a 290px sidebar). sidebarPosition: "right" stops the wrap and shrinks the graph instead; "bottom" always stacks the sidebar below. The plot's bottom/left margins grow automatically with the axis font size so large axis labels never clip.

In the visual builder, all of these live in the meta section (font scale, title size, graph width, sidebar width, sidebar position) and on each axis / label / sidebar item; every number box is pre-seeded with its default value, and a value is only written into the spec once you change it away from the default.

The scope: params and derived

param (an entry in params):

Property Type Required Meaning
name string yes How you refer to it in expressions.
value number yes Starting value.
label string no Caption shown on its slider.
min, max number no Range. Having both makes a slider and bounds dragging.
step number no Rounding increment (e.g. 0.1).

derived is an object mapping a name to an expression. Entries are computed in order and may use earlier ones. A value may also be a nested object of expressions (used to group related values):

"derived": {
  "qStar": "(supplyIntercept - demandIntercept) / (demandSlope - supplySlope)",
  "pStar": "demandIntercept + demandSlope * qStar"
}

Params and derived together form the scope: the set of names any expression in the spec can use.

Axes and panels

axis object: label (string), min (number, required), max (number, required), ticks (number; 0 for none, omit for ~6), color (optional palette name or hex; tints the axis line, tick labels, and axis title — defaults to gray), size (optional px; sizes this axis's title and its tick numbers, default 12, still scaled by fontScale). Set color/size in the builder via the axis form.

axes object: { "x": axis, "y": axis }.

panel (an entry in panels): axes (required), objects (required, array of graph objects), id (string, optional), height (number, optional and not yet honored; panels currently stack with equal height).

Graph objects

Every graph object has these three in common: type (string, required, selects the kind), color (a palette name or hex), and show (a boolean expression; when it is false the object is hidden). Below, only the type-specific properties are listed. In the visual builder every color / fill / stroke field is a color picker (a wheel for any color, plus a clear-to-default button).

curve — a function y = f(x)

Property Type Required Meaning
fn expression in x yes The function to plot.
min, max expr no x-range to draw over (defaults to the axis range).
strokeWidth number no Line thickness.
label label no Text on the curve.

line — a straight line

Give it either two points, or a point and a slope.

Property Type Required Meaning
point point one form A point it passes through.
point2 point with point A second point (draws the segment between the two).
slope expr with point Slope, instead of a second point.
intercept expr alt. y-value at x = 0 (used with slope, no point).
min, max expr no x-range for the slope form.
strokeWidth number no Thickness.
label label no Text on the line.

point — a marked coordinate

Property Type Required Meaning
x, y expr yes Its location.
r number no Radius in pixels.
droplines object no { "x": ..., "y": ... }. A value of true drops a dashed line to that axis; a string drops the line and prints that (dynamic) text as a KaTeX label.
draggable drag no Lets the user drag it to change a param.
label label no Text by the point.
hint string no Small caption (e.g. "drag").

drag object: param (string, required, which param to change), axis ("x" or "y", which direction), expression (optional; maps the dragged coordinate, available as drag, to the param value, e.g. "drag / xIntercept").

area — a shaded region between two curves

Property Type Required Meaning
top expr in x yes Upper edge. A number (e.g. 0) or an expression string both work.
bottom expr in x yes Lower edge. A number or expression string.
xFrom, xTo expr yes The x-range to fill.
opacity number no 0 to 1 (default 0.15).

rectangle

Property Type Required Meaning
a, b point yes Two opposite corners.
fill color or "none" no Interior.
stroke color no Border.
opacity number no 0 to 1.

arrow

Property Type Required Meaning
begin, end point yes Endpoints.
double boolean no Arrowheads on both ends.
trim number no Fraction to shorten each end (e.g. 0.01).
label label no Text at the middle.

segment — a plain line between two points

a (point), b (point), strokeWidth (number), label.

label — free-floating text

text (string; may contain LaTeX, $...$ delimiters, and ${expr} interpolation), x (expr), y (expr), plus the label properties below (size, color, dx, dy, align).

Labels

Wherever a label property appears it is a label object:

Property Type Meaning
text string The text. Rendered with KaTeX. A string with no $ is rendered whole as math, so bare LaTeX like Q^d or \text{price} works. It also accepts $...$ / $$...$$ delimiters like the sidebar, so $x$ and mixed text like price is $p$ render correctly. May contain ${expr}, replaced by the live value.
x expr Where along the object to place it.
dx, dy number Pixel nudges.
align string "right" right-aligns it.
color color Text color.
size number Font size (px) of this label (default 13). Still scaled by fontScale.

Sidebar

sidebar object: { "controls": [ control, ... ], "hidden": false }.

control: title (string), titleSize (number, px, default 15), sliders (array), divs (array).

Games (normal form)

Set the top-level game property (instead of axes/panels) to draw a payoff matrix with best-response and Nash reasoning built in. The runtime picks the view: a plain matrix, an IESDS step-through, or the 2×2 mixed-strategy diagrams, depending on the flags below.

game object:

Property Type Required Meaning
players array of exactly two game player yes Row player first, column player second.
payoffs 3-D array yes payoffs[i][j] is a two-element array [u1, u2] — the row player's and column player's payoff when the row player picks strategy i and the column player picks strategy j. Each entry is an expr, so payoffs can depend on params.
showBestResponses boolean no Tint each player's best-response cells in that player's color (the visible, non-bold cue).
showNash boolean no Ring the pure-strategy Nash equilibria (cells that are a best response for both).
iesds boolean no Iterated elimination of strictly dominated strategies: adds Prev/Next buttons that dim eliminated strategies one round at a time and outline the dominating strategy.
mixed boolean no 2×2 only. Adds the mixed-strategy view: best-response-in-the-unit-square diagram, indifference plots, and p/q sliders.
title string no Heading for the game.

game player: name (string, required), strategies (array of strings, required — the row or column labels), color (optional palette name or hex; defaults to the built-in player1 / player2 colors). The builder's game mode has a color picker for each player.

Grid convention: payoffs.length = number of row strategies = players[0].strategies.length; each payoffs[i].length = number of column strategies = players[1].strategies.length. For mixed and iesds's cleanest behavior, keep it 2×2; the plain matrix, best-response tint, and Nash ring work for any m×n.

Trees (extensive form)

Set the top-level tree property to draw an extensive-form game, laid out automatically (no manual coordinates) and optionally solved by backward induction.

tree object:

Property Type Required Meaning
players array of tree player yes Index order matters: a node's player and a terminal's payoffs are positional to this list.
root tree node yes The top of the tree.
orientation string no "topDown" (default) or "leftRight".
backwardInduction boolean no Adds Prev/Next fold-back: reveals decisions from the leaves inward, bolds each chosen edge in the acting player's color, shows the value folding back, and rings the subgame-perfect outcome.
title string no Heading for the tree.

tree player: name (string, required), color (optional; defaults to the player1..player3 / nature palette by index).

tree node is recursive and is one of two kinds:

tree action: label (string, the edge label / action name) and child (a tree node — the node reached by taking that action).

Depth and breadth: 2+ players and arbitrary branching are supported; layout is automatic so wide or deep trees just get more spread. Very large trees will eventually crowd, but there is no fixed cap for teaching-sized games.

Repeated games

Set the top-level repeated property to draw an infinitely repeated 2×2 game (a prisoner's dilemma by default): the stage matrix, a discounting timeline (cooperate-forever vs the best one-shot deviation), and a threshold plot where the two discounted values cross at δ*. A strategy selector switches between grim trigger, tit-for-tat, and an n-period-forgiving trigger.

repeated object: all optional. players (two names, default You / Rival), cooperate / defect (action labels), T / R / P / S / delta / n (the scope names the runtime reads the stage payoffs, discount factor, and punishment length from — defaults are those literals, so just define matching params), strategies (subset of ["grim", "tft", "nPeriod"], default all three), periods (timeline horizon, default 9). The payoffs and δ live in params so they become sliders, and every threshold updates live. Grim trigger sustains cooperation iff δ ≥ (T−R)/(T−P); tit-for-tat needs a higher δ; the n-period trigger sits between the two.

Dynamics (discrete-time paths)

There is no dedicated "dynamics" primitive. Discrete-time models (like the cobweb) are authored with two existing tools:

  1. Unroll the recurrence into derived. Because derived entries compute in order and can reference earlier ones, "p1": "45 - 1.5*p0", "p2": "45 - 1.5*p1", … is the state path. Define one entry per period up to a fixed maximum.
  2. Gate each step with a periods slider. Make an integer param periods (min:0 … max:n, step:1) and put "show": "periods>=k" on every segment and point belonging to step k. Dragging periods then reveals the path one period at a time — ideal for lecturing.

Reactive verdict text (which stability regime you are in) is just sidebar divs with show expressions on a stability quantity, e.g. "show": "abs(K) > 1". The two cobweb samples (samples/cobweb.spec.json, samples/partial-cobweb.spec.json) are the worked examples, and python/kgspec/dynamics.py's cobweb(...) generates the pattern programmatically. Caveat: the recurrence is unrolled at authoring time, so the maximum horizon is fixed by how many derived entries you write; there is no runtime loop.

Expressions

Any field marked expr is a number or a string evaluated by mathjs against the scope. Inside a curve/area, the variable x is also available; inside a drag expression, the dragged coordinate is drag. You can use + - * /, ^ for powers, comparisons, and / or, a ternary cond ? a : b, member access like demand.slope, and math functions like sqrt(...), min(...), abs(...). An object whose expression throws (e.g. a misspelled name) is isolated — it simply does not draw, with a one-time console warning, rather than blanking the whole graph.

Colors

A color is a palette name or a hex/rgb string. Built-in names include the plain set (blue, red, green, orange, purple, pink, gray, black), the managerial aliases (demand, supply, price, equilibrium, surplus, profit, marginalRevenue, cost, budget, utility, arrow, fill3), and the game/tree player colors (player1, player2, player3, nature, plus cooperate / defect for repeated games). Add or override any of these with the top-level colors property, for example "colors": { "demand": "#1d4ed8" }. In the visual builder, any color field (object colors, fills, label text, axis color, game player colors) is a color picker: a wheel for any color plus a clear-to-default button. Picking from the wheel writes a hex; a named palette color already in a spec is preserved and shown resolved to its hex, and names can still be typed by hand in the code editor.