Origin: https://appunite.com/blog/let-the-force-be-with-livebook
Save this as .livemd
and open with running Livebook server to evaluate.
Mix.install([
{:tesla, "~> 1.4"},
{:jason, "~> 1.2"},
{:vega_lite, "~> 0.1"},
{:kino, "~> 0.3"}
])
Star Wars API Client module:
defmodule StarWarsClient do
use Tesla
plug(Tesla.Middleware.BaseUrl, "https://swapi.dev/api")
plug(Tesla.Middleware.JSON)
def vehicles(), do: get("/vehicles")
end
{:ok, %{body: body}} = StarWarsClient.vehicles()
# just to test that we can retrieve and work with the data
# body["results"]
# |> Enum.sort_by(&(String.to_integer(&1["max_atmosphering_speed"])))
# |> List.last()
# |> Map.get("name")
vehicles_json = body["results"]
length_and_speed =
vehicles_json
|> Enum.map(
&%{
"length" => elem(Float.parse(&1["length"]), 0),
"max_atmosphering_speed" => elem(Float.parse(&1["max_atmosphering_speed"]), 0)
}
)
VegaLite.new(width: 750, height: 400)
|> VegaLite.data_from_values(length_and_speed)
|> VegaLite.mark(:line)
|> VegaLite.encode_field(:x, "length")
|> VegaLite.encode_field(:y, "max_atmosphering_speed")
classes =
vehicles_json
|> Enum.frequencies_by(&Map.get(&1, "vehicle_class"))
|> Enum.map(fn {k, v} -> %{"Vehicle class" => k, "Value" => v} end)
VegaLite.new(width: 650, height: 400)
|> VegaLite.data_from_values(classes)
|> VegaLite.mark(:arc)
|> VegaLite.encode_field(:theta, "Value", type: :quantitative)
|> VegaLite.encode_field(:color, "Vehicle class", type: :nominal)
|> VegaLite.config(view: [stroke: nil])
vehicles_rows =
vehicles_json
|> Enum.map(&"| #{&1["name"]} | #{&1["vehicle_class"]} | #{&1["manufacturer"]} |\n")
"""
| Name | Vehicle class | Manufacturer |
|------|---------------|--------------|
#{vehicles_rows}
"""
|> Kino.Markdown.new()