diff --git a/.circleci/config.yml b/.circleci/config.yml index 5b4b5d8..2f98de4 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -100,10 +100,6 @@ jobs: at: . - <<: *install_hex_rebar - # - run: - # name: Start Chrome Driver - # command: /usr/local/bin/chromedriver - # background: true - run: name: mix test command: mix coveralls.html @@ -148,7 +144,7 @@ jobs: - << parameters.project_name >>/priv/plts - run: - command: mix dialyzer --halt-exit-status + command: mix dialyzer working_directory: ~/project/<< parameters.project_name >> no_output_timeout: 20m @@ -219,13 +215,13 @@ workflows: filters: tags: only: /v.*/ - # - dialyzer: - # project_name: uncharted - # name: uncharted_dialyzer - # requires: - # - uncharted_credo - # - uncharted_test - # - uncharted_check_formatted + - dialyzer: + project_name: uncharted + name: uncharted_dialyzer + requires: + - uncharted_credo + - uncharted_test + - uncharted_check_formatted - check-formatted: project_name: uncharted_phoenix @@ -251,10 +247,10 @@ workflows: filters: tags: only: /v.*/ - # - dialyzer: - # project_name: uncharted_phoenix - # name: uncharted_phoenix_dialyzer - # requires: - # - uncharted_phoenix_credo - # - uncharted_phoenix_test - # - uncharted_phoenix_check_formatted + - dialyzer: + project_name: uncharted_phoenix + name: uncharted_phoenix_dialyzer + requires: + - uncharted_phoenix_credo + - uncharted_phoenix_test + - uncharted_phoenix_check_formatted diff --git a/run_ci_check.sh b/run_ci_check.sh new file mode 100755 index 0000000..014a813 --- /dev/null +++ b/run_ci_check.sh @@ -0,0 +1,3 @@ +#! /bin/sh + +cd uncharted && MIX_ENV=test mix do format --check-formatted, test, credo --strict && cd ../uncharted_phoenix && MIX_ENV=test mix do format --check-formatted, test, credo --strict diff --git a/run_dialyzer.sh b/run_dialyzer.sh new file mode 100755 index 0000000..62bb811 --- /dev/null +++ b/run_dialyzer.sh @@ -0,0 +1,3 @@ +#! /bin/sh + +cd uncharted && mix dialyzer && cd ../uncharted_phoenix && mix dialyzer diff --git a/uncharted/lib/uncharted.ex b/uncharted/lib/uncharted.ex index 8823e7c..98547e8 100644 --- a/uncharted/lib/uncharted.ex +++ b/uncharted/lib/uncharted.ex @@ -13,10 +13,12 @@ defmodule Uncharted do is a union type """ @type dataset :: - Uncharted.ColumnChart.Dataset.t() + Uncharted.BarChart.Dataset.t() + | Uncharted.ColumnChart.Dataset.t() + | Uncharted.LineChart.Dataset.t() | Uncharted.PieChart.Dataset.t() + | Uncharted.PolarChart.Dataset.t() | Uncharted.ProgressChart.Dataset.t() - | Uncharted.BarChart.Dataset.t() @type gen_chart :: %{ title: String.t(), colors: %{color_name() => String.t() | Uncharted.Gradient.t()}, diff --git a/uncharted/lib/uncharted/axes/magnitude_axis.ex b/uncharted/lib/uncharted/axes/magnitude_axis.ex index 084f914..d010bbc 100644 --- a/uncharted/lib/uncharted/axes/magnitude_axis.ex +++ b/uncharted/lib/uncharted/axes/magnitude_axis.ex @@ -2,10 +2,11 @@ defmodule Uncharted.Axes.MagnitudeAxis do @moduledoc """ Exposes a struct representing configuration for an axis that has values that increase in a particular direction """ - defstruct [:min, :max, :step, :label, grid_lines: &__MODULE__.default_grid_lines_fun/2] + defstruct [:min, :max, :step, :label, :units, grid_lines: &__MODULE__.default_grid_lines_fun/2] @type min :: number() @type max :: number() - @type step :: integer() + @type num_steps :: integer() + @type units :: atom() @typedoc """ A function that takes a tuple with a minimum and maximum value that @@ -13,10 +14,11 @@ defmodule Uncharted.Axes.MagnitudeAxis do is used to determine the spacial offsets of the labels on the axis and the gridlines of the chart. """ - @type grid_lines_func :: ({min, max}, step -> list(Float.t())) + @type grid_lines_func :: ({min, max}, num_steps() -> list(float())) @type t() :: %__MODULE__{ min: number(), max: number(), + units: units(), step: integer(), label: String.t() | nil, grid_lines: grid_lines_func @@ -30,10 +32,10 @@ defmodule Uncharted.Axes.MagnitudeAxis do when you create a `Uncharted.Axes.MagnitudeAxis` struct, this implementation will be provided used. """ - @spec default_grid_lines_fun({min, max}, step) :: list(Float.t()) - def default_grid_lines_fun({min, max}, step) do - min..max - |> Enum.take_every(div(max - min, step)) - |> Enum.drop(1) + @spec default_grid_lines_fun({min, max}, num_steps()) :: list(float()) + def default_grid_lines_fun({min, max}, num_steps) do + step_size = (max - min) / (num_steps * 1.0) + + Enum.map(0..num_steps, fn step -> step * step_size end) end end diff --git a/uncharted/lib/uncharted/axes/polar_axes.ex b/uncharted/lib/uncharted/axes/polar_axes.ex new file mode 100644 index 0000000..66c81bd --- /dev/null +++ b/uncharted/lib/uncharted/axes/polar_axes.ex @@ -0,0 +1,13 @@ +defmodule Uncharted.Axes.PolarAxes do + @moduledoc """ + A struct for representing a polar coordinate system's axes + """ + + defstruct [:r, :t, show_gridlines: true] + + @type t() :: %__MODULE__{ + r: Uncharted.Axes.MagnitudeAxis.t(), + t: Uncharted.Axes.MagnitudeAxis.t(), + show_gridlines: boolean() + } +end diff --git a/uncharted/lib/uncharted/bar_chart/bar.ex b/uncharted/lib/uncharted/bar_chart/bar.ex index c01530b..6537569 100644 --- a/uncharted/lib/uncharted/bar_chart/bar.ex +++ b/uncharted/lib/uncharted/bar_chart/bar.ex @@ -6,12 +6,12 @@ defmodule Uncharted.BarChart.Bar do defstruct [:height, :offset, :label, :bar_height, :bar_offset, :bar_width, :fill_color] @type t() :: %__MODULE__{ - height: Float.t(), - offset: Float.t(), + height: float(), + offset: float(), label: String.t(), - bar_height: Float.t(), - bar_offset: Float.t(), - bar_width: Float.t(), + bar_height: float(), + bar_offset: float(), + bar_width: float(), fill_color: atom() } end diff --git a/uncharted/lib/uncharted/bar_chart/dataset.ex b/uncharted/lib/uncharted/bar_chart/dataset.ex index d098feb..9b4b7a9 100644 --- a/uncharted/lib/uncharted/bar_chart/dataset.ex +++ b/uncharted/lib/uncharted/bar_chart/dataset.ex @@ -5,7 +5,7 @@ defmodule Uncharted.BarChart.Dataset do defstruct [:axes, :data] @type t() :: %__MODULE__{ - axes: Uncharted.BaseAxes.t(), + axes: Uncharted.Axes.BaseAxes.t(), data: list(Uncharted.BaseDatum.t()) } end diff --git a/uncharted/lib/uncharted/base_chart.ex b/uncharted/lib/uncharted/base_chart.ex index c702db3..5131769 100644 --- a/uncharted/lib/uncharted/base_chart.ex +++ b/uncharted/lib/uncharted/base_chart.ex @@ -12,7 +12,7 @@ defmodule Uncharted.BaseChart do @type t() :: %__MODULE__{ title: String.t(), - colors: %{color_name() => String.t() | Gradient.t()}, + colors: %{color_name() => String.t() | Uncharted.Gradient.t()}, dataset: Uncharted.dataset() } diff --git a/uncharted/lib/uncharted/column_chart/column.ex b/uncharted/lib/uncharted/column_chart/column.ex index 5df748b..1b7f692 100644 --- a/uncharted/lib/uncharted/column_chart/column.ex +++ b/uncharted/lib/uncharted/column_chart/column.ex @@ -6,12 +6,12 @@ defmodule Uncharted.ColumnChart.Column do defstruct [:width, :offset, :label, :bar_width, :bar_offset, :column_height, :fill_color] @type t() :: %__MODULE__{ - width: Float.t(), - offset: Float.t(), + width: float(), + offset: float(), label: String.t(), - bar_width: Float.t(), - bar_offset: Float.t(), - column_height: Float.t(), + bar_width: float(), + bar_offset: float(), + column_height: float(), fill_color: atom() } end diff --git a/uncharted/lib/uncharted/column_chart/dataset.ex b/uncharted/lib/uncharted/column_chart/dataset.ex index 173fa22..2f72426 100644 --- a/uncharted/lib/uncharted/column_chart/dataset.ex +++ b/uncharted/lib/uncharted/column_chart/dataset.ex @@ -5,7 +5,7 @@ defmodule Uncharted.ColumnChart.Dataset do defstruct [:axes, :data] @type t() :: %__MODULE__{ - axes: Uncharted.BaseAxes.t(), + axes: Uncharted.Axes.BaseAxes.t(), data: list(Uncharted.BaseDatum.t()) } end diff --git a/uncharted/lib/uncharted/line_chart/base_chart_impl.ex b/uncharted/lib/uncharted/line_chart/base_chart_impl.ex index 39f85c8..0a52a4a 100644 --- a/uncharted/lib/uncharted/line_chart/base_chart_impl.ex +++ b/uncharted/lib/uncharted/line_chart/base_chart_impl.ex @@ -1,6 +1,6 @@ defimpl Uncharted.LineChart, for: Uncharted.BaseChart do alias Uncharted.BaseChart - alias Uncharted.ColumnChart.Dataset + alias Uncharted.LineChart.Dataset alias Uncharted.LineChart.{Line, Point} def points(%BaseChart{dataset: nil}), do: [] diff --git a/uncharted/lib/uncharted/line_chart/dataset.ex b/uncharted/lib/uncharted/line_chart/dataset.ex new file mode 100644 index 0000000..036f2ff --- /dev/null +++ b/uncharted/lib/uncharted/line_chart/dataset.ex @@ -0,0 +1,11 @@ +defmodule Uncharted.LineChart.Dataset do + @moduledoc """ + Struct representing a dataset for a basic column chart. + """ + defstruct [:axes, :data] + + @type t() :: %__MODULE__{ + axes: Uncharted.Axes.XYAxes.t(), + data: list(Uncharted.BaseDatum.t()) + } +end diff --git a/uncharted/lib/uncharted/line_chart/line_chart.ex b/uncharted/lib/uncharted/line_chart/line_chart.ex index 08b1376..65008cd 100644 --- a/uncharted/lib/uncharted/line_chart/line_chart.ex +++ b/uncharted/lib/uncharted/line_chart/line_chart.ex @@ -1,9 +1,9 @@ defprotocol Uncharted.LineChart do - @spec points(Uncharted.chart() | Uncharted.ColumnChart.Dataset.t()) :: + @spec points(Uncharted.chart() | Uncharted.LineChart.Dataset.t()) :: list(Uncharted.LineChart.Point.t()) def points(chart) - @spec lines(Uncharted.chart() | Uncharted.ColumnChart.Dataset.t()) :: + @spec lines(Uncharted.chart() | Uncharted.LineChart.Dataset.t()) :: list(Uncharted.LineChart.Line.t()) def lines(chart) end diff --git a/uncharted/lib/uncharted/line_chart/point.ex b/uncharted/lib/uncharted/line_chart/point.ex index 3bd1f48..41e5c22 100644 --- a/uncharted/lib/uncharted/line_chart/point.ex +++ b/uncharted/lib/uncharted/line_chart/point.ex @@ -8,7 +8,7 @@ defmodule Uncharted.LineChart.Point do @type t :: %__MODULE__{ label: String.t(), fill_color: atom(), - x_offset: Float.t(), - y_offset: Float.t() + x_offset: float(), + y_offset: float() } end diff --git a/uncharted/lib/uncharted/pie_chart/pie_slice.ex b/uncharted/lib/uncharted/pie_chart/pie_slice.ex index 85c0592..30f55b9 100644 --- a/uncharted/lib/uncharted/pie_chart/pie_slice.ex +++ b/uncharted/lib/uncharted/pie_chart/pie_slice.ex @@ -7,7 +7,7 @@ defmodule Uncharted.PieChart.PieSlice do @type t() :: %__MODULE__{ label: String.t(), - percentage: Float.t(), + percentage: float(), fill_color: atom() } end diff --git a/uncharted/lib/uncharted/polar_chart/base_chart_impl.ex b/uncharted/lib/uncharted/polar_chart/base_chart_impl.ex new file mode 100644 index 0000000..8edfade --- /dev/null +++ b/uncharted/lib/uncharted/polar_chart/base_chart_impl.ex @@ -0,0 +1,22 @@ +defimpl Uncharted.PolarChart, for: Uncharted.BaseChart do + alias Uncharted.BaseChart + alias Uncharted.PolarChart.Dataset + alias Uncharted.PolarChart.Point + + def points(%BaseChart{dataset: nil}), do: [] + def points(%BaseChart{dataset: dataset}), do: points(dataset) + def points(%Dataset{data: []}), do: [] + + def points(%Dataset{ + data: data + }) do + data + |> Enum.map(fn datum -> + %Point{ + label: datum.name, + r: Enum.at(datum.values, 0), + t: Enum.at(datum.values, 1) + } + end) + end +end diff --git a/uncharted/lib/uncharted/polar_chart/dataset.ex b/uncharted/lib/uncharted/polar_chart/dataset.ex new file mode 100644 index 0000000..6a5f01d --- /dev/null +++ b/uncharted/lib/uncharted/polar_chart/dataset.ex @@ -0,0 +1,11 @@ +defmodule Uncharted.PolarChart.Dataset do + @moduledoc """ + Struct representing a dataset for a basic polar chart. + """ + defstruct [:axes, :data] + + @type t() :: %__MODULE__{ + axes: Uncharted.Axes.PolarAxes.t(), + data: list(Uncharted.BaseDatum.t()) + } +end diff --git a/uncharted/lib/uncharted/polar_chart/point.ex b/uncharted/lib/uncharted/polar_chart/point.ex new file mode 100644 index 0000000..1cd141a --- /dev/null +++ b/uncharted/lib/uncharted/polar_chart/point.ex @@ -0,0 +1,13 @@ +defmodule Uncharted.PolarChart.Point do + @moduledoc """ + A struct representing a Point on a polar r, t coordinate chart + """ + + defstruct [:label, :r, :t] + + @type t :: %__MODULE__{ + label: String.t(), + r: float(), + t: float() + } +end diff --git a/uncharted/lib/uncharted/polar_chart/polar_chart.ex b/uncharted/lib/uncharted/polar_chart/polar_chart.ex new file mode 100644 index 0000000..4bc4926 --- /dev/null +++ b/uncharted/lib/uncharted/polar_chart/polar_chart.ex @@ -0,0 +1,5 @@ +defprotocol Uncharted.PolarChart do + @spec points(Uncharted.chart() | Uncharted.PolarChart.Dataset.t()) :: + list(Uncharted.PolarChart.Point.t()) + def points(chart) +end diff --git a/uncharted/mix.exs b/uncharted/mix.exs index 48c5f3e..0e27026 100644 --- a/uncharted/mix.exs +++ b/uncharted/mix.exs @@ -20,7 +20,7 @@ defmodule Uncharted.MixProject do compilers: Mix.compilers(), dialyzer: [ plt_add_apps: ~w(ex_unit mix)a, - plt_add_deps: :transitive, + plt_add_deps: :app_tree, plt_file: {:no_warn, "priv/plts/dialyzer.plt"} # ignore_warnings: "../.dialyzer-ignore.exs" ], diff --git a/uncharted/test/uncharted/line_chart_test.exs b/uncharted/test/uncharted/line_chart_test.exs index 7b33b9f..9caacaf 100644 --- a/uncharted/test/uncharted/line_chart_test.exs +++ b/uncharted/test/uncharted/line_chart_test.exs @@ -1,7 +1,7 @@ defmodule Uncharted.LineChartTest do alias Uncharted.{BaseChart, BaseDatum, LineChart} alias Uncharted.Axes.{MagnitudeAxis, XYAxes} - alias Uncharted.ColumnChart.Dataset + alias Uncharted.LineChart.Dataset alias Uncharted.LineChart.Line use ExUnit.Case diff --git a/uncharted/test/uncharted/polar_chart_test.exs b/uncharted/test/uncharted/polar_chart_test.exs new file mode 100644 index 0000000..c91e174 --- /dev/null +++ b/uncharted/test/uncharted/polar_chart_test.exs @@ -0,0 +1,49 @@ +defmodule Uncharted.PolarChartTest do + alias Uncharted.{BaseChart, BaseDatum, PolarChart} + alias Uncharted.Axes.{MagnitudeAxis, PolarAxes} + alias Uncharted.PolarChart.Dataset + alias Uncharted.PolarChart.Line + use ExUnit.Case + + @radial_axis %MagnitudeAxis{min: 0, max: 12.0} + @angular_axis %MagnitudeAxis{min: 0, max: 2.0, units: :radians, step: 4} + @axes %PolarAxes{r: @radial_axis, t: @angular_axis} + @data [ + %BaseDatum{name: "Point One", values: [1, 1.3]}, + %BaseDatum{name: "Point Two", values: [5, 1.0]}, + %BaseDatum{name: "Point Three", values: [6, 0.5]}, + %BaseDatum{name: "Point Four", values: [8, 1.8]}, + %BaseDatum{name: "Point Five", values: [10, 0.3]} + ] + @dataset %Dataset{data: @data, axes: @axes} + @chart %BaseChart{title: "title", dataset: @dataset} + + describe "points/1" do + test "returns the number of points that make up the dataset" do + assert length(PolarChart.points(@chart)) == length(@data) + end + + test "returns point labels" do + points = Enum.map(PolarChart.points(@chart), & &1.label) + labels = Enum.map(@data, & &1.name) + + assert points + |> Enum.zip(labels) + |> Enum.all?(fn {actual, expected} -> actual == expected end) + end + + test "assigns point r (radial distance) value as first element in datum.values" do + r_values = Enum.map(PolarChart.points(@chart), & &1.r) + expected_r_values = [1, 5, 6, 8, 10] + + assert r_values == expected_r_values + end + + test "assigns point t (angular distance) value as first element in datum.values" do + t_values = Enum.map(PolarChart.points(@chart), & &1.t) + expected_t_values = [1.3, 1.0, 0.5, 1.8, 0.3] + + assert t_values == expected_t_values + end + end +end diff --git a/uncharted_phoenix/lib/uncharted_phoenix/components/_r_axis.html.leex b/uncharted_phoenix/lib/uncharted_phoenix/components/_r_axis.html.leex new file mode 100644 index 0000000..26f5e36 --- /dev/null +++ b/uncharted_phoenix/lib/uncharted_phoenix/components/_r_axis.html.leex @@ -0,0 +1,5 @@ +" class="columns__lines"> + <%= for radius <- @grid_lines do %> + + <% end %> + diff --git a/uncharted_phoenix/lib/uncharted_phoenix/components/_t_axis.html.leex b/uncharted_phoenix/lib/uncharted_phoenix/components/_t_axis.html.leex new file mode 100644 index 0000000..fbbeef2 --- /dev/null +++ b/uncharted_phoenix/lib/uncharted_phoenix/components/_t_axis.html.leex @@ -0,0 +1,5 @@ +" class="columns__lines"> + <%= for %Line{start: %{x_offset: x1, y_offset: y1}, end: %{x_offset: x2, y_offset: y2}} <- angular_to_cartesian_gridlines(@grid_lines, @chart.dataset.axes.r.max) do %> + + <% end %> + diff --git a/uncharted_phoenix/lib/uncharted_phoenix/components/component_impl.ex b/uncharted_phoenix/lib/uncharted_phoenix/components/component_impl.ex index 82bbde1..f4d5266 100644 --- a/uncharted_phoenix/lib/uncharted_phoenix/components/component_impl.ex +++ b/uncharted_phoenix/lib/uncharted_phoenix/components/component_impl.ex @@ -3,12 +3,11 @@ defimpl Uncharted.Component, for: Uncharted.BarChart.Dataset do end defimpl Uncharted.Component, for: Uncharted.ColumnChart.Dataset do - def for_dataset(%{axes: axes}) do - case axes do - %{x: _x_axis, y: _y_axis} -> UnchartedPhoenix.LiveLineComponent - _ -> UnchartedPhoenix.LiveColumnComponent - end - end + def for_dataset(_dataset), do: UnchartedPhoenix.LiveColumnComponent +end + +defimpl Uncharted.Component, for: Uncharted.LineChart.Dataset do + def for_dataset(_dataset), do: UnchartedPhoenix.LiveLineComponent end defimpl Uncharted.Component, for: Uncharted.PieChart.Dataset do diff --git a/uncharted_phoenix/lib/uncharted_phoenix/components/live_line.ex b/uncharted_phoenix/lib/uncharted_phoenix/components/live_line.ex index 4791d66..e1ee0b3 100644 --- a/uncharted_phoenix/lib/uncharted_phoenix/components/live_line.ex +++ b/uncharted_phoenix/lib/uncharted_phoenix/components/live_line.ex @@ -8,7 +8,7 @@ defmodule UnchartedPhoenix.LiveLineComponent do def update(assigns, socket) do x_axis = assigns.chart.dataset.axes.x y_axis = assigns.chart.dataset.axes.y - # # Hardcode the number of steps to take as 5 for now + # Hardcode the number of steps to take as 5 for now x_grid_lines = x_axis.grid_lines.({x_axis.min, x_axis.max}, 5) x_grid_line_offsetter = fn grid_line -> 100 * grid_line / x_axis.max end diff --git a/uncharted_phoenix/lib/uncharted_phoenix/components/live_line.html.leex b/uncharted_phoenix/lib/uncharted_phoenix/components/live_line.html.leex index c43bfe8..cee1aa7 100644 --- a/uncharted_phoenix/lib/uncharted_phoenix/components/live_line.html.leex +++ b/uncharted_phoenix/lib/uncharted_phoenix/components/live_line.html.leex @@ -30,7 +30,7 @@ " class="line_dots"> - <%= for %Point{x_offset: x_offset, y_offset: y_offset, fill_color: fill_color} <- @points do %> + <%= for %CartesianPoint{x_offset: x_offset, y_offset: y_offset, fill_color: fill_color} <- @points do %> (r_axis.max - grid_line) / r_axis.max end + + t_grid_lines = t_axis.grid_lines.({t_axis.min, t_axis.max}, 4) + t_grid_line_offsetter = fn grid_line -> (t_axis.max - grid_line) / t_axis.max end + + socket = + socket + |> assign(:chart, assigns.chart) + |> assign(:points, Uncharted.PolarChart.points(assigns.chart)) + |> assign(:r_grid_lines, r_grid_lines) + |> assign(:r_grid_line_offsetter, r_grid_line_offsetter) + |> assign(:t_grid_lines, t_grid_lines) + |> assign(:t_grid_line_offsetter, t_grid_line_offsetter) + + {:ok, socket} + end + + def render(assigns) do + Phoenix.View.render(UnchartedPhoenix.ComponentView, "live_polar.html", assigns) + end +end diff --git a/uncharted_phoenix/lib/uncharted_phoenix/components/live_polar.html.leex b/uncharted_phoenix/lib/uncharted_phoenix/components/live_polar.html.leex new file mode 100644 index 0000000..1506e8f --- /dev/null +++ b/uncharted_phoenix/lib/uncharted_phoenix/components/live_polar.html.leex @@ -0,0 +1,36 @@ +
+ " class="polar__chart" aria-labelledby="chartTitle" role="group" width="100%" height="100%" viewBox="0 0 700 400" style="overflow: visible;"> + <%= Chart.title(@chart) %> + + <%#= render "_y_axis.html", chart: @chart, grid_lines: @y_grid_lines, offsetter: @y_grid_line_offsetter %> + <%#= render "_bar_grid_line_labels.html", chart: @chart, grid_lines: @x_grid_lines, offsetter: @x_grid_line_offsetter %> + + " class="line__graph" width="90%" height="92%" x="10%" y="0"> + " class="line__results" width="100%" height="100%" x="0%" y="0%" viewBox="<%= polar_viewbox(@chart) %>"> + <%= render "_t_axis.html", chart: @chart, grid_lines: @t_grid_lines, offsetter: @t_grid_line_offsetter %> + <%= render "_r_axis.html", chart: @chart, grid_lines: @r_grid_lines, offsetter: @r_grid_line_offsetter %> + " class="line_dots"> + <%= for %CartesianPoint{x_offset: x_offset, y_offset: y_offset, label: label} <- convert_points(@points) do %> + + + + + + <%= label %> + + <% end %> + + + + + + + + + <%= render "_color_defs.html", chart: @chart %> + + +
diff --git a/uncharted_phoenix/lib/uncharted_phoenix/views/component_view.ex b/uncharted_phoenix/lib/uncharted_phoenix/views/component_view.ex index 5d81143..e544175 100644 --- a/uncharted_phoenix/lib/uncharted_phoenix/views/component_view.ex +++ b/uncharted_phoenix/lib/uncharted_phoenix/views/component_view.ex @@ -8,7 +8,9 @@ defmodule UnchartedPhoenix.ComponentView do alias Uncharted.{Chart, Gradient} alias Uncharted.ColumnChart.Column - alias Uncharted.LineChart.{Line, Point} + alias Uncharted.LineChart.Line + alias Uncharted.LineChart.Point, as: CartesianPoint + alias Uncharted.PolarChart.Point, as: PolarPoint def color_to_fill(colors, name) do case Map.get(colors, name) do @@ -55,9 +57,39 @@ defmodule UnchartedPhoenix.ComponentView do def svg_polyline_points(points) do points - |> Enum.map(fn %Point{x_offset: x, y_offset: y} -> "#{10 * x},#{1000 - 10 * y}" end) + |> Enum.map(fn %CartesianPoint{x_offset: x, y_offset: y} -> "#{10 * x},#{1000 - 10 * y}" end) |> List.insert_at(0, "#{hd(points).x_offset * 10},1000") |> List.insert_at(-1, "#{List.last(points).x_offset * 10},1000") |> Enum.join(" ") end + + def convert_points(polar_points) do + Enum.map(polar_points, &polar_to_cartesian/1) + end + + def polar_to_cartesian(%PolarPoint{r: r, t: t, label: label}) do + %CartesianPoint{ + x_offset: r * :math.cos(t), + y_offset: r * :math.sin(t), + label: label + } + end + + def angular_to_cartesian_gridlines(angles, r_max) do + Enum.map(angles, fn t -> + polar_to_cartesian(%PolarPoint{r: 0, t: 0}, %PolarPoint{r: r_max, t: t}) + end) + end + + def polar_to_cartesian(%PolarPoint{} = p1, %PolarPoint{} = p2) do + %Line{ + start: polar_to_cartesian(p1), + end: polar_to_cartesian(p2) + } + end + + def polar_viewbox(%{dataset: %{axes: %{r: %{max: r_max}}}} = _chart) do + [-r_max, -r_max, 2 * r_max, 2 * r_max] + |> Enum.join(" ") + end end diff --git a/uncharted_phoenix/mix.exs b/uncharted_phoenix/mix.exs index 50f4a8e..11535e1 100644 --- a/uncharted_phoenix/mix.exs +++ b/uncharted_phoenix/mix.exs @@ -20,7 +20,7 @@ defmodule UnchartedPhoenix.MixProject do compilers: [:phoenix] ++ Mix.compilers(), dialyzer: [ plt_add_apps: ~w(ex_unit mix)a, - plt_add_deps: :transitive, + plt_add_deps: :app_tree, plt_file: {:no_warn, "priv/plts/dialyzer.plt"} # ignore_warnings: "../.dialyzer-ignore.exs" ], diff --git a/uncharted_phoenix/test/uncharted_phoenix/components/live_line_test.exs b/uncharted_phoenix/test/uncharted_phoenix/components/live_line_test.exs index 8fe13c7..87ecdd2 100644 --- a/uncharted_phoenix/test/uncharted_phoenix/components/live_line_test.exs +++ b/uncharted_phoenix/test/uncharted_phoenix/components/live_line_test.exs @@ -1,7 +1,7 @@ defmodule UnchartedPhoenix.LiveLineComponentTest do alias Uncharted.BaseChart alias Uncharted.Axes.{MagnitudeAxis, XYAxes} - alias Uncharted.ColumnChart.Dataset + alias Uncharted.LineChart.Dataset alias UnchartedPhoenix.LiveLineComponent import Phoenix.LiveViewTest use ExUnit.Case diff --git a/uncharted_phoenix/test/uncharted_phoenix_test.exs b/uncharted_phoenix/test/uncharted_phoenix_test.exs index b71ee1e..a84a109 100644 --- a/uncharted_phoenix/test/uncharted_phoenix_test.exs +++ b/uncharted_phoenix/test/uncharted_phoenix_test.exs @@ -68,7 +68,7 @@ defmodule UnchartedPhoenixTest do line_chart = %Uncharted.BaseChart{ @base_chart - | dataset: %Uncharted.ColumnChart.Dataset{axes: xy_axes, data: []} + | dataset: %Uncharted.LineChart.Dataset{axes: xy_axes, data: []} } assert render_component(DummyLiveComponent, chart: line_chart) =~