defmodule GitGudWeb.CiWallLive.Layout do
@moduledoc """
How the live CI wall tiles `n` cards across at most `max_cols`
columns.
Up to `max_cols` cards, each is a column of its own, full height. Past
that the columns fill up from the right: the 7th card (of 6 columns)
pairs the rightmost column, the 8th the next one in, until every
column holds two; then the rightmost becomes three, and so on. So the
first cards in order keep the most room, and the columns to their
right hold one more card than them, or as many.
Laid out as a CSS grid that flows down its columns: `rows` is a
multiple of every column's card count (k and k + 1 cards need
k·(k + 1) rows), and each card spans `rows / cards in its column`.
"""
@type t :: %{cols: non_neg_integer(), rows: non_neg_integer(), spans: [pos_integer()]}
@spec tile(non_neg_integer(), pos_integer()) :: t()
def tile(0, _max_cols), do: %{cols: 0, rows: 0, spans: []}
def tile(n, max_cols) when is_integer(n) and n > 0 and is_integer(max_cols) and max_cols > 0 do
cols = min(n, max_cols)
base = div(n, cols)
# The rightmost `extra` columns hold one card more than the rest.
extra = rem(n, cols)
rows = if extra == 0, do: base, else: base * (base + 1)
# The leftmost `cols - extra` columns, `base` cards each, come first.
short = (cols - extra) * base
spans = for i <- 0..(n - 1), do: if(i < short, do: div(rows, base), else: div(rows, base + 1))
%{cols: cols, rows: rows, spans: spans}
end
@doc "How many cards each column holds, left to right (for the toolbar)."
@spec column_counts(non_neg_integer(), pos_integer()) :: [pos_integer()]
def column_counts(0, _max_cols), do: []
def column_counts(n, max_cols) do
cols = min(n, max_cols)
base = div(n, cols)
extra = rem(n, cols)
List.duplicate(base, cols - extra) ++ List.duplicate(base + 1, extra)
end
end
neiam
/gitgud
Git Gud
public · Issues · Pulls · Labels · Forks · Compare · Actions success · Badges · Packages
⭐
1
Log in to mark this repository.
1.9 KiB · text
History
b868907