Documentation
¶
Overview ¶
Package formula evaluates arithmetic across trend series — the derived metrics every mature analytics tool has and this engine did not.
"Signups per visitor", "revenue per active user", "the share of sessions that rage-clicked" are all one series divided by another, and without them a person has to export two charts and open a spreadsheet. That is the moment they stop using the tool.
The whole file is about one thing being right: a derived number must be MORE honest than the series it came from, not less. Two failures are easy and both are silent — dividing Tuesday's numerator by Wednesday's denominator because the series were not aligned, and rendering a divide-by-zero as 0 so "no data" and "genuinely zero" become the same pixel.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Point ¶
type Point struct {
Date time.Time `json:"date"`
Value float64 `json:"value"`
Defined bool `json:"defined"`
// Why explains an undefined point in words, because "—" in a chart with no reason is the
// thing that makes someone assume the tool is broken.
Why string `json:"why,omitempty"`
}
Point is one bucket of a derived series.
Value is only meaningful when Defined. A float64 cannot carry "undefined" — NaN would be swallowed by JSON, and 0 is a lie — so the flag travels alongside it and every consumer has to look at it.
type Result ¶
type Result struct {
Expression string `json:"expression"`
Points []Point `json:"points"`
// Defined/Undefined counts, so a caller can see at a glance that half the chart is missing
// rather than discovering it by hovering.
Defined int `json:"defined"`
Undefined int `json:"undefined"`
Note string `json:"note,omitempty"`
}
Result is the derived series plus what it was computed from.
func Evaluate ¶
Evaluate computes `expr` over the named series.
Operands are the series names (A, B, signups, …) and decimal literals. Operators are + - * / and parentheses, with the usual precedence. Deliberately not a general expression language: this runs on user input, and every feature added here is a new way to be surprised by a number.