Skip to content

Instantly share code, notes, and snippets.

@cr0t
Last active December 3, 2023 10:17
Show Gist options
  • Save cr0t/d7463f670ea02799e38882b0648b3d45 to your computer and use it in GitHub Desktop.
Save cr0t/d7463f670ea02799e38882b0648b3d45 to your computer and use it in GitHub Desktop.
Example of using Tesla, VegaLite, and Kino libraries in Elixir's Livebook

Playground

Section

Origin: https://appunite.com/blog/let-the-force-be-with-livebook

Save this as .livemd and open with running Livebook server to evaluate.

Prerequisites

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

Fetching from Star Wars API

{: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"]

Vehicles: length and speed

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")

Vehicles: classes

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])

Example on using Kino

vehicles_rows =
  vehicles_json
  |> Enum.map(&"| #{&1["name"]} | #{&1["vehicle_class"]} | #{&1["manufacturer"]} |\n")

"""
| Name | Vehicle class | Manufacturer |
|------|---------------|--------------|
#{vehicles_rows}
"""
|> Kino.Markdown.new()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment