-module(sparklinekit@unicode).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/sparklinekit/unicode.gleam").
-export([render/1, render_ints/1]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(
" Unicode-block sparklines for terminal output.\n"
"\n"
" ```gleam\n"
" import sparklinekit/unicode\n"
"\n"
" pub fn shape() -> String {\n"
" unicode.render([1.0, 5.0, 22.0, 13.0, 5.0, 2.0, 7.0])\n"
" // -> \"▁▂█▅▂▁▃\"\n"
" }\n"
" ```\n"
"\n"
" The eight block characters `▁▂▃▄▅▆▇█` partition the value range\n"
" into eight equal levels. Empty input returns `\"\"`. A single value,\n"
" or a series where every value is the same, renders as a flat line\n"
" at the middle level (`▄`).\n"
).
-file("src/sparklinekit/unicode.gleam", 68).
-spec block_for(float(), float(), float()) -> binary().
block_for(Value, Lo, Hi) ->
Normalized = sparklinekit@internal@scale:unit(Value, Lo, Hi),
Raw = begin
_pipe = Normalized * erlang:float(8 - 1),
erlang:round(_pipe)
end,
Index = sparklinekit@internal@scale:clamp_int(Raw, 0, 8 - 1),
gleam@string:slice(<<"▁▂▃▄▅▆▇█"/utf8>>, Index, 1).
-file("src/sparklinekit/unicode.gleam", 64).
-spec middle_block() -> binary().
middle_block() ->
gleam@string:slice(<<"▁▂▃▄▅▆▇█"/utf8>>, 3, 1).
-file("src/sparklinekit/unicode.gleam", 38).
?DOC(
" Render `values` as a string of Unicode block characters.\n"
"\n"
" - `[]` produces `\"\"`.\n"
" - `[v]` produces a single middle-level block (`▄`).\n"
" - All-equal inputs produce a string of middle-level blocks.\n"
" - Otherwise each value is mapped into one of eight levels by\n"
" normalising against the observed minimum and maximum.\n"
"\n"
" Use [`render_ints`](#render_ints) if your data series is `List(Int)`.\n"
).
-spec render(list(float())) -> binary().
render(Values) ->
case Values of
[] ->
<<""/utf8>>;
[_] ->
middle_block();
_ ->
{Lo, Hi} = sparklinekit@internal@scale:min_max(Values),
case Lo =:= Hi of
true ->
_pipe = Values,
_pipe@1 = gleam@list:map(
_pipe,
fun(_) -> middle_block() end
),
erlang:list_to_binary(_pipe@1);
false ->
_pipe@2 = Values,
_pipe@3 = gleam@list:map(
_pipe@2,
fun(Value) -> block_for(Value, Lo, Hi) end
),
erlang:list_to_binary(_pipe@3)
end
end.
-file("src/sparklinekit/unicode.gleam", 60).
?DOC(
" Convenience wrapper around [`render/1`](#render) for `List(Int)`\n"
" inputs. Equivalent to `render(list.map(values, int.to_float))`.\n"
).
-spec render_ints(list(integer())) -> binary().
render_ints(Values) ->
render(gleam@list:map(Values, fun erlang:float/1)).