diff options
| author | Marcos Magueta <maguetamarcos@gmail.com> | 2026-03-05 23:42:15 -0300 |
|---|---|---|
| committer | Marcos Magueta <maguetamarcos@gmail.com> | 2026-03-05 23:42:15 -0300 |
| commit | 8c640a262969ef44cd8bc0e0abe95e2a54f4c3f5 (patch) | |
| tree | 84f9ddd9e41236fb7a6f540aab07e65db9bc93cb /src/visualizer.erl | |
| parent | 295c6a5a1f2b0db9d756ffe7bf413553a0c02737 (diff) | |
| download | Sakura-8c640a262969ef44cd8bc0e0abe95e2a54f4c3f5.tar.gz Sakura-8c640a262969ef44cd8bc0e0abe95e2a54f4c3f5.zip | |
ocaml re-migration
Diffstat (limited to 'src/visualizer.erl')
| -rw-r--r-- | src/visualizer.erl | 348 |
1 files changed, 0 insertions, 348 deletions
diff --git a/src/visualizer.erl b/src/visualizer.erl deleted file mode 100644 index 75f85d1..0000000 --- a/src/visualizer.erl +++ /dev/null @@ -1,348 +0,0 @@ -%%% @doc Relation Visualizer - Multiple Rendering Modes -%%% -%%% Provides various visual representations for nested relational data. -%%% Supports different modes optimized for different use cases. -%%% -%%% == Modes == -%%% -%%% - table - Classic flat table (default) -%%% - nested_table - Tables within table cells -%%% - tree - Hierarchical tree view with indentation -%%% - linked_tables - Separate linked tables for nested relations -%%% - outline - Indented outline format -%%% -%%% == Usage == -%%% <pre> -%%% Results = query_planner:collect(DB, Plan), -%%% visualizer:render(Results, tree). -%%% visualizer:render(Results, nested_table). -%%% </pre> -%%% -%%% @author Nekoma Team -%%% @copyright 2025 - --module(visualizer). - --export([render/1, - render/2, - modes/0]). - --type render_mode() :: table - | nested_table - | tree - | linked_tables - | outline. - --export_type([render_mode/0]). - -%%% Public API - -%% @doc Render tuples with default mode (table). --spec render([map()]) -> ok. -render(Tuples) -> - render(Tuples, table). - -%% @doc Render tuples with specified visualization mode. --spec render([map()], render_mode()) -> ok. -render([], _Mode) -> - io:format("(no results)~n"), - ok; -render(Tuples, table) -> - render_table(Tuples); -render(Tuples, nested_table) -> - render_nested_table(Tuples); -render(Tuples, tree) -> - render_tree(Tuples); -render(Tuples, linked_tables) -> - render_linked_tables(Tuples); -render(Tuples, outline) -> - render_outline(Tuples). - -%% @doc List available rendering modes. --spec modes() -> [render_mode()]. -modes() -> - [table, nested_table, tree, linked_tables, outline]. - -%%% Rendering Implementations - -%% Mode 1: Table with proper column width calculation -render_table(Tuples) -> - AllKeys = get_all_keys(Tuples), - - % Calculate column widths based on content - Widths = calculate_column_widths(Tuples, AllKeys), - - io:format("~n"), - print_separator_with_widths(Widths), - print_row_with_widths([atom_to_list(K) || K <- AllKeys], Widths), - print_separator_with_widths(Widths), - - lists:foreach( - fun(Tuple) -> - Values = [format_value_for_table(maps:get(K, Tuple, undefined)) || K <- AllKeys], - print_row_with_widths(Values, Widths) - end, - Tuples - ), - print_separator_with_widths(Widths), - io:format("~n~b tuple(s)~n~n", [length(Tuples)]), - ok. - -calculate_column_widths(Tuples, Keys) -> - lists:map( - fun(Key) -> - % Start with header width - HeaderWidth = length(atom_to_list(Key)), - - % Find max value width in this column - MaxValueWidth = lists:foldl( - fun(Tuple, MaxW) -> - Value = maps:get(Key, Tuple, undefined), - ValueStr = format_value_for_table(Value), - max(MaxW, length(ValueStr)) - end, - HeaderWidth, - Tuples - ), - - max(12, MaxValueWidth) % Minimum width of 12 - end, - Keys - ). - -format_value_for_table(V) when is_map(V) -> - % Format nested map as inline representation - Keys = [K || K <- maps:keys(V), K =/= meta], - Parts = [atom_to_list(K) ++ ":" ++ format_value(maps:get(K, V)) || K <- Keys], - "[" ++ string:join(Parts, ", ") ++ "]"; -format_value_for_table(V) -> - format_value(V). - -print_separator_with_widths(Widths) -> - io:format("+"), - lists:foreach( - fun(W) -> - io:format("~s+", [lists:duplicate(W + 2, $-)]) - end, - Widths - ), - io:format("~n"). - -print_row_with_widths(Values, Widths) -> - io:format("| "), - lists:foreach( - fun({Val, Width}) -> - io:format("~*s | ", [-Width, Val]) - end, - lists:zip(Values, Widths) - ), - io:format("~n"). - -%% Mode 2: Nested tables (tables within cells) -render_nested_table(Tuples) -> - io:format("~n=== Nested Table View ===~n~n"), - lists:foreach( - fun(Tuple) -> - render_tuple_nested(Tuple, 0) - end, - Tuples - ), - io:format("~n~b tuple(s)~n~n", [length(Tuples)]), - ok. - -render_tuple_nested(Tuple, Indent) -> - Keys = [K || K <- maps:keys(Tuple), K =/= meta], - IndentStr = lists:duplicate(Indent, $\s), - - io:format("~s+-- Tuple~n", [IndentStr]), - lists:foreach( - fun(Key) -> - Value = maps:get(Key, Tuple), - case is_map(Value) andalso (Key =/= meta) of - true -> - % Nested tuple - render as inner table - io:format("~s| ~s:~n", [IndentStr, atom_to_list(Key)]), - io:format("~s| +-------------------------+~n", [IndentStr]), - NestedKeys = maps:keys(Value), - lists:foreach( - fun(NK) -> - NV = format_value(maps:get(NK, Value)), - io:format("~s| | ~-10s : ~-10s |~n", - [IndentStr, atom_to_list(NK), NV]) - end, - NestedKeys - ), - io:format("~s| +-------------------------+~n", [IndentStr]); - false -> - % Simple value - io:format("~s| ~-15s : ~s~n", - [IndentStr, atom_to_list(Key), format_value(Value)]) - end - end, - Keys - ), - io:format("~s+--~n", [IndentStr]). - -%% Mode 3: Tree view with hierarchy -render_tree(Tuples) -> - io:format("~n=== Tree View ===~n~n"), - io:format("+-- Relation (~b tuples)~n", [length(Tuples)]), - render_tuples_as_tree(Tuples, "| ", length(Tuples)), - io:format("~n"), - ok. - -render_tuples_as_tree([], _Prefix, _Total) -> - ok; -render_tuples_as_tree([Tuple], Prefix, Total) -> - io:format("~s~n~s+-- Row ~b~n", [Prefix, Prefix, Total]), - render_tuple_as_tree(Tuple, Prefix ++ " "); -render_tuples_as_tree([Tuple | Rest], Prefix, Total) -> - Index = Total - length(Rest), - io:format("~s~n~s+-- Row ~b~n", [Prefix, Prefix, Index]), - render_tuple_as_tree(Tuple, Prefix ++ "| "), - render_tuples_as_tree(Rest, Prefix, Total). - -render_tuple_as_tree(Tuple, Prefix) -> - Keys = [K || K <- maps:keys(Tuple), K =/= meta], - render_attrs_as_tree(Keys, Tuple, Prefix). - -render_attrs_as_tree([], _Tuple, _Prefix) -> - ok; -render_attrs_as_tree([Key], Tuple, Prefix) -> - Value = maps:get(Key, Tuple), - case is_map(Value) andalso (Key =/= meta) of - true -> - io:format("~s+-- ~s:~n", [Prefix, atom_to_list(Key)]), - render_tuple_as_tree(Value, Prefix ++ " "); - false -> - io:format("~s+-- ~s: ~s~n", - [Prefix, atom_to_list(Key), format_value(Value)]) - end; -render_attrs_as_tree([Key | Rest], Tuple, Prefix) -> - Value = maps:get(Key, Tuple), - case is_map(Value) andalso (Key =/= meta) of - true -> - io:format("~s+-- ~s:~n", [Prefix, atom_to_list(Key)]), - render_tuple_as_tree(Value, Prefix ++ "| "), - render_attrs_as_tree(Rest, Tuple, Prefix); - false -> - io:format("~s+-- ~s: ~s~n", - [Prefix, atom_to_list(Key), format_value(Value)]), - render_attrs_as_tree(Rest, Tuple, Prefix) - end. - -%% Mode 4: Linked tables (parent + separate child tables) -render_linked_tables(Tuples) -> - io:format("~n=== Linked Tables View ===~n~n"), - - % Collect nested relations with parent references - {FlatTuples, NestedRels} = extract_nested_relations_with_refs(Tuples), - - % Render main table - io:format("Main Relation:~n"), - render_table(FlatTuples), - - % Render nested tables with parent references - case NestedRels of - [] -> ok; - _ -> - io:format("~nNested Relations:~n"), - lists:foreach( - fun({RowIdx, AttrName, NestedTuple}) -> - io:format("~n[~s for Row ~b]:~n", [atom_to_list(AttrName), RowIdx]), - render_table([NestedTuple]) - end, - NestedRels - ) - end, - ok. - -extract_nested_relations_with_refs(Tuples) -> - % Process tuples with index tracking - {FlatTuples, NestedRels} = lists:foldl( - fun(Tuple, {FlatAcc, NestedAcc}) -> - RowIdx = length(FlatAcc) + 1, - - % Flatten this tuple - FlatTuple = maps:map( - fun(K, V) when is_map(V), K =/= meta -> - lists:flatten(io_lib:format("[~b]", [RowIdx])); - (_K, V) -> V - end, - Tuple - ), - - % Extract nested relations with parent reference - Nested = lists:filtermap( - fun(K) -> - case maps:get(K, Tuple) of - V when is_map(V), K =/= meta -> - {true, {RowIdx, K, V}}; - _ -> - false - end - end, - maps:keys(Tuple) - ), - - {[FlatTuple | FlatAcc], Nested ++ NestedAcc} - end, - {[], []}, - Tuples - ), - - {lists:reverse(FlatTuples), lists:reverse(NestedRels)}. - -%% Mode 5: Outline format (indented text) -render_outline(Tuples) -> - io:format("~n=== Outline View ===~n~n"), - lists:foreach( - fun(Tuple) -> - render_tuple_outline(Tuple, 0) - end, - Tuples - ), - io:format("~n~b tuple(s)~n~n", [length(Tuples)]), - ok. - -render_tuple_outline(Tuple, Indent) -> - Keys = [K || K <- maps:keys(Tuple), K =/= meta], - IndentStr = lists:duplicate(Indent, $\s), - - io:format("~s+-- Tuple~n", [IndentStr]), - lists:foreach( - fun(Key) -> - Value = maps:get(Key, Tuple), - case is_map(Value) andalso (Key =/= meta) of - true -> - io:format("~s| ~s:~n", [IndentStr, atom_to_list(Key)]), - render_tuple_outline(Value, Indent + 4); - false -> - io:format("~s| ~s: ~s~n", - [IndentStr, atom_to_list(Key), format_value(Value)]) - end - end, - Keys - ), - io:format("~s+--~n", [IndentStr]). - -%%% Helper Functions - -get_all_keys(Tuples) -> - lists:usort( - lists:flatmap( - fun(Tuple) -> - [K || K <- maps:keys(Tuple), K =/= meta] - end, - Tuples - ) - ). - -format_value(undefined) -> "(null)"; -format_value(V) when is_integer(V) -> integer_to_list(V); -format_value(V) when is_float(V) -> float_to_list(V, [{decimals, 2}]); -format_value(V) when is_atom(V) -> atom_to_list(V); -format_value(V) when is_binary(V) -> binary_to_list(V); -format_value(V) when is_list(V) -> V; -format_value(V) when is_map(V) -> "(nested)"; -format_value(_) -> "(complex)". |
