Expresso.Element.Chart.Waterfall (expresso v0.1.0)

Copy Markdown View Source

A waterfall chart: a start value, the changes to it, and the totals between them

Expresso.Element.Chart sends each function of a chart of the family :waterfall to this module: the check, the assigns, the layout, the marks and the table. docs/waterfall-charts.md gives the design.

The chart has one series. Its first value is the start, and it draws as a total. Each other number is a change, and it draws as a floating column from the running total before it. The atom :total marks a total column, and {:total, value} also gives the value that the author expects. columns/1 calculates the base, the end and the running total of each column.

With reveal true, the check puts the columns into groups: members/2 gives the group of each column. Group 0 holds the start and the totals of totals :grow, and the chart draws it outside the groups, so it shows with the chart and does not dim. Each change is a group, and a total of totals :complete goes into the group of the column before it. Each group is a copy of the series with the indexes of its columns in columns, and it is a child of the chart, so it takes its step from reveal.

A state is one set of values of the channels: one state for each group that shows, from group 0. A total of totals :grow holds in each state the running total of the changes that show, so it grows or shrinks at the step of each change, and its value counts. A chart with frames has one more state for each later frame, after the states of reveal in the first frame. rules/1 writes the channels of each state at its steps.

Each column has its place in the channels of Expresso.Element.Chart.Motion: --u<i> and --v<i> for the corner at the top left of column i, and --w<i> and --h<i> for its size. The style attribute of the column reads the channels with the value of the first state as the fallback, so a chart of one state needs no rule.

Summary

Types

One column: its type, its change, the value at its base and at its end, and the running total after it

A value of the series of a waterfall chart: a change, or the mark of a total

Functions

Make the assigns of a waterfall chart that the other kinds do not have

Read a cell of a value from the CSV file of a waterfall chart

Check the options and the series of a waterfall chart

Return the columns of the values of a waterfall chart

Tell whether the axis of a waterfall chart does not hold zero

Add the layout of a waterfall chart to its assigns: the axis, the box of the plot, the function pos from a value to a coordinate on the value axis, and the columns of each state

Return the steps that a waterfall chart takes before its first change: 1 with the groups of reveal, so the start and the totals show alone at the first step, else 0

Return the group of each column of a waterfall chart with reveal

Tell whether the columns of a waterfall chart move: with the steps of reveal, or with the effect :grow

Return the options of Expresso.Element.Chart.Csv for the file of a waterfall chart: the reader of a cell, and the words of its error

Draw the content of the SVG of a waterfall chart: the axis, the columns, their labels and the connectors

Return the CSS rules of the states of a waterfall chart with reveal or with frames

Return the places of the columns, of their labels and of the connectors in each state, and the channels that hold them

Write a change with its sign

Return the headers and the rows of the table of a waterfall chart

Types

column()

@type column() :: %{
  type: :total | :up | :down,
  change: number() | nil,
  from: number(),
  to: number(),
  total: number()
}

One column: its type, its change, the value at its base and at its end, and the running total after it

value()

@type value() :: number() | :total | {:total, number()}

A value of the series of a waterfall chart: a change, or the mark of a total

Functions

assigns(chart)

@spec assigns(Expresso.Element.Chart.t()) :: map()

Make the assigns of a waterfall chart that the other kinds do not have

Expresso.Element.Chart.get_assigns/1 merges them into the assigns of a chart with an axis.

cell(text)

@spec cell(String.t()) :: value() | nil

Read a cell of a value from the CSV file of a waterfall chart

A cell holds a number, the word total, or the word total and the value that the author expects. The function returns nil for another cell.

iex> Expresso.Element.Chart.Waterfall.cell("40")
40
iex> Expresso.Element.Chart.Waterfall.cell("total")
:total
iex> Expresso.Element.Chart.Waterfall.cell(" Total 1,250 ")
{:total, 1250}
iex> Expresso.Element.Chart.Waterfall.cell("many")
nil

check(chart)

@spec check(Expresso.Element.Chart.t()) ::
  {:ok, Expresso.Element.Chart.t()} | {:error, String.t()}

Check the options and the series of a waterfall chart

Expresso.Element.Chart calls this function after the check of the categories. The chart has one series with one value for each category. The first value is a number, and each other value is a number, :total or {:total, value}. The sum before {:total, value} agrees with the value, and each column is inside value_range.

columns(list)

@spec columns([value()]) :: [column()]

Return the columns of the values of a waterfall chart

A total starts at zero and ends at the running total. A change starts at the running total before it and ends at the new running total.

iex> Expresso.Element.Chart.Waterfall.columns([50, 40, -10, :total])
[
  %{type: :total, change: nil, from: 0, to: 50, total: 50},
  %{type: :up, change: 40, from: 50, to: 90, total: 90},
  %{type: :down, change: -10, from: 90, to: 80, total: 80},
  %{type: :total, change: nil, from: 0, to: 80, total: 80}
]

cut?(map)

@spec cut?(map()) :: boolean()

Tell whether the axis of a waterfall chart does not hold zero

Such an axis has a break mark at its base, and each total column has a break mark at its base.

inner_block(name, list)

(macro)

layout(assigns)

@spec layout(map()) :: map()

Add the layout of a waterfall chart to its assigns: the axis, the box of the plot, the function pos from a value to a coordinate on the value axis, and the columns of each state

A state is one set of values of the channels. A chart without steps has one state. The axis holds zero, or it has the ends of value_range. The value axis goes up the left side of a vertical chart, and along the bottom of a horizontal chart.

lead(chart)

@spec lead(Expresso.Element.Chart.t()) :: 0 | 1

Return the steps that a waterfall chart takes before its first change: 1 with the groups of reveal, so the start and the totals show alone at the first step, else 0

members(list, totals)

@spec members([value()], :grow | :complete) :: [non_neg_integer()]

Return the group of each column of a waterfall chart with reveal

The start is in group 0, and each change starts a new group. A total is in group 0 with totals :grow, and in the group of the column before it with totals :complete.

iex> Expresso.Element.Chart.Waterfall.members([50, 40, 30, :total, 10, :total], :grow)
[0, 1, 2, 0, 3, 0]
iex> Expresso.Element.Chart.Waterfall.members([50, 40, 30, :total, 10, :total], :complete)
[0, 1, 2, 2, 3, 3]

moves?(chart)

@spec moves?(Expresso.Element.Chart.t()) :: boolean()

Tell whether the columns of a waterfall chart move: with the steps of reveal, or with the effect :grow

reader()

@spec reader() :: keyword()

Return the options of Expresso.Element.Chart.Csv for the file of a waterfall chart: the reader of a cell, and the words of its error

render(assigns)

@spec render(map()) :: Phoenix.HTML.safe()

Draw the content of the SVG of a waterfall chart: the axis, the columns, their labels and the connectors

render_slot(slot, arg)

(macro)

rules(chart)

@spec rules(Expresso.Element.Chart.t()) :: [String.t()]

Return the CSS rules of the states of a waterfall chart with reveal or with frames

The state of group k holds at the steps of group k at which group k + 1 and the later frames do not show, and the state of a later frame holds at the steps of that frame. The first state is the value of each channel in the style attribute, so it needs no rule.

scene(assigns)

@spec scene(map()) :: %{
  marks: [map()],
  spans: [map()],
  channels: [{String.t(), [number()]}]
}

Return the places of the columns, of their labels and of the connectors in each state, and the channels that hold them

A column has the channels u, v, w and h, its label of the total or of the running total has l, its number n, the signed change has m, and the connector at its left has j. A label and a connector have their place on the value axis in the channel, and their place on the axis of the categories in their style. Expresso.Element.Chart.Motion leaves out a channel that has the same value in each state.

signed(value)

@spec signed(number()) :: String.t()

Write a change with its sign

iex> Expresso.Element.Chart.Waterfall.signed(40)
"+40"
iex> Expresso.Element.Chart.Waterfall.signed(-2.5)
"-2.5"

table(assigns)

@spec table(map()) :: %{headers: [String.t() | nil], rows: [[String.t()]]}

Return the headers and the rows of the table of a waterfall chart

The table has one row for each column, with its category, its change and the running total after it. A total has no change.