Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

Simulador de una colmena de abejas concurrentes

abejas.livemd

Simulador de una colmena de abejas concurrentes

Mix.install([
  :kino, :kino_vega_lite
])

Section

🧠 ¿Qué representa? Cada abeja es un proceso que trabaja, comunica su estado y eventualmente muere o termina. Usamos Livebook para ver este enjambre en acción.

🐝 Módulo para una abeja (proceso individual)

defmodule Abeja do
  def start(id, coordinador_pid) do
    spawn(fn -> loop(id, coordinador_pid) end)
  end

  defp loop(id, coordinador_pid) do
    estados = ["esperando", "volando", "comiendo"]
    estado_aleatorio = Enum.random(estados)

    send(coordinador_pid, {:estado, id, estado_aleatorio})

    Process.sleep(:rand.uniform(1000)) # añade aleatoriedad también al tiempo de espera
    loop(id, coordinador_pid)
  end
end
{:module, Abeja, <<70, 79, 82, 49, 0, 0, 9, ...>>, {:loop, 2}}

🧭 Coordinador que recibe mensajes y actualiza un gráfico

defmodule Coordinador do
 def start() do
    # Configuramos el gráfico con los nombres de los campos esperados
    vl =
      VegaLite.new(width: 600, height: 400, padding: 20)
      |> VegaLite.data_from_values([], name: "abejas")
      |> VegaLite.mark(:bar)
      |> VegaLite.encode_field(:x, "estado", type: :nominal)
      |> VegaLite.encode_field(:y, "id", type: :ordinal, aggregate: :count)
      |> VegaLite.encode_field(:color, "estado", type: :nominal)

    grafico = Kino.VegaLite.new(vl)
    Kino.render(grafico)

    spawn(fn -> loop(grafico) end)
  end

  defp loop(grafico) do
    receive do
      {:estado, id, estado} ->
        nuevo_estado = %{"id" => id, "estado" => estado}

        Kino.VegaLite.push(grafico, nuevo_estado, dataset: "abejas")

        loop(grafico)
    end
  end 
end
{:module, Coordinador, <<70, 79, 82, 49, 0, 0, 10, ...>>, {:loop, 1}}

🚀 Lanzar 5000 abejas concurrentes


coordinador = Coordinador.start()

1..5
|> Enum.each(fn id ->
  Abeja.start(id, coordinador)
end)
:ok