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

🥋 Book I - Matrix

books/book1.livemd

🥋 Book I - Matrix

Welcome to Book I

host = :inet.gethostname()
host = :erl_epmd.names()
input = Kino.Input.text("Your name")
name = Kino.Input.read(input)
{:ok, class} = Dojo.Class.join(self(), "book1", %Dojo.Disciple{name: name, action: "away"})
coordinate = [{3, 4}, {2, 5}, {2, 6}]

DojoKino.Animate.new(1..10, fn index ->
  Kino.Markdown.new(Dojo.Conway.genesis("blinker", 10, index, coordinate))
end)
f = &Dojo.Conway.reduce_genesis("blinker", 7, &1, coordinate)
Dojo.PubSub.publish({name, f}, :animate, "class:book1")
defmodule ECM do
  def run(start_str, rule, times) do
    IO.puts("rule : #{rule}")
    each(start_str, rule_pattern(rule), times)
  end

  defp rule_pattern(rule) do
    list =
      Integer.to_string(rule, 2)
      |> String.pad_leading(8, "0")
      |> String.codepoints()
      |> Enum.reverse()

    Enum.map(0..7, fn i -> Integer.to_string(i, 2) |> String.pad_leading(3, "0") end)
    |> Enum.zip(list)
    |> Map.new()
  end

  defp each(_, _, 0), do: :ok

  defp each(str, patterns, times) do
    IO.puts(String.replace(str, "0", "⬜") |> String.replace("1", "⬛"))
    str2 = String.last(str) <> str <> String.first(str)

    next_str =
      Enum.map_join(0..(String.length(str) - 1), fn i ->
        Map.get(patterns, String.slice(str2, i, 3))
      end)

    each(next_str, patterns, times - 1)
  end
end

pad = String.duplicate("0", 14)
str = pad <> "1" <> pad
ECM.run(str, 90, 4)
DojoKino.Animate.new(1..10, fn index -> ECM.run(str, 90, index) end)
defmodule GOL do
  # ...

  def next_generation(grid) do
    # Define the convolution kernel for the Game of Life rules
    kernel = [
      [1, 1, 1],
      [1, 0, 1],
      [1, 1, 1]
    ]

    # Apply the convolution to the grid
    convolution(grid, kernel)
  end

  defp convolution(grid, kernel) do
    # Implement the convolution operation here
    # This involves sliding the kernel over the grid and applying the rules
    # For simplicity, we'll assume a basic implementation that counts neighbors
    # and applies the Game of Life rules
    Enum.map(grid, fn row, y ->
      Enum.map(row, fn cell, x ->
        # Calculate the sum of the kernel applied to the cell
        sum =
          Enum.sum(Enum.with_index(kernel), fn {row, ky}, i ->
            Enum.sum(Enum.with_index(row), fn cell, kx ->
              if kx + i < 0 or kx + i >= length(row) or ky + y < 0 or ky + y >= length(grid) do
                0
              else
                Enum.at(Enum.at(grid, ky + y), kx + i)
              end
            end)
          end)

        # Apply the Game of Life rules
        if cell == 1 and (sum == 2 or sum == 3) do
          1
        else
          if cell == 0 and sum == 3 do
            1
          else
            0
          end
        end
      end)
    end)
  end
end
defmodule KinoGuide.ShellCell do
  use Kino.JS
  use Kino.JS.Live
  use Kino.SmartCell, name: "Shell script"

  @impl true
  def init(_attrs, ctx) do
    {:ok, ctx, editor: [attribute: "source"]}
  end

  @impl true
  def handle_connect(ctx) do
    {:ok, %{}, ctx}
  end

  @impl true
  def to_attrs(_ctx) do
    %{}
  end

  @impl true
  def to_source(attrs) do
    quote do
      System.shell(
        unquote(quoted_multiline(attrs["source"])),
        into: IO.stream(),
        stderr_to_stdout: true
      )
      |> elem(1)
    end
    |> Kino.SmartCell.quoted_to_string()
  end

  defp quoted_multiline(string) do
    {:<<>>, [delimiter: ~s["""]], [string <> "\n"]}
  end

  asset "main.js" do
    """
    export function init(ctx, payload) {
      ctx.importCSS("main.css");

      root.innerHTML = `
        
          Shell script
        
      `;
    }
    """
  end

  asset "main.css" do
    """
    .app {
      padding: 8px 16px;
      border: solid 1px #cad5e0;
      border-radius: 0.5rem 0.5rem 0 0;
      border-bottom: none;
    }
    """
  end
end

Kino.SmartCell.register(KinoGuide.ShellCell)
defmodule Kino.TailwindPlayground do
  use Kino.JS
  use Kino.JS.Live
  use Kino.SmartCell, name: "Tailwind Playground"
  require Logger

  @impl true
  def init(attrs, ctx) do
    {:ok, assign(ctx, initial_html: attrs["html"] || ""),
     editor: [attribute: "html", language: "html", placement: :top]}
  end

  @impl true
  def handle_connect(ctx) do
    {:ok, %{}, ctx}
  end

  @impl true
  def handle_event("initial-render", %{}, ctx) do
    Process.send_after(self(), {:display_html, ctx.assigns.initial_html}, 100)
    {:noreply, ctx}
  end

  @impl true
  def to_attrs(_ctx) do
    %{}
  end

  @impl true
  def to_source(attrs) do
    # we can't encode ctx in attrs so we send ourselves a message in order to display the html.
    send(self(), {:display_html, attrs["html"]})
    "Kino.nothing()"
  end

  @impl true
  def handle_info({:display_html, html}, ctx) do
    broadcast_event(ctx, "display-html", %{"html" => html})
    {:noreply, ctx}
  end

  asset "main.css" do
    """
    .wrapper {
      position: relative;
      width: 100%;
      height: 100%;
      overflow-x: auto;
      background-color: white;
    }

    svg {
      pointer-events: none;
    }

    .size-btn {
      color: white;
      border-radius: 8px;
      border-style: none;
      background-color: #33394c;
      width: 28px;
      height: 28px;
      display: flex;
      align-items: center;
      justify-content: center;
      padding: 4px;
    }

    .active {
      background-color: #495e7c;
    }

    .button-header {
      padding: 12px;
      background-color: #0f182a;
      display: flex;
      gap: 8px;
    }

    #iframe {
      background-color: white;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      border: none;
      display: block;
      margin-left: auto;
      margin-right: auto;
      overflow: auto;
    }

    #iframe-container {
      max-width: 100%;
      display: block;
      background-color: #292c34;
      height: 570px;
      resize: vertical;
      overflow: hidden;
      position: relative;
      padding: 0 5px 5px;
    }
    """
  end

  asset "main.js" do
    """
    export function init(ctx, payload) {
      ctx.importCSS("main.css");

      ctx.root.innerHTML = `
        
          
            
              xs
            
            
              sm
            
            
              md
            
            
              
                
              
            
          
          
            
          
        
      `
      ctx
        .importJS(
          "https://cdn.tailwindcss.com?plugins=forms,typography,aspect-ratio"
        )
        .then(() => {
          let iframe = ctx.root.querySelector("#iframe");
          let buttons = document.querySelectorAll(".size-btn");

          iframe.srcdoc = `
            
              
              
            
            
            
          `
          buttons.forEach((btn) => {
            btn.addEventListener("click", (e) => {
              iframe.style.maxWidth = e.target.dataset.width;
              buttons.forEach((btn) => { btn.classList.remove("active") })
              e.target.classList.add("active")
            });
          });

          ctx.handleEvent("display-html", ({ html }) => {
            let body = iframe.contentWindow.document.querySelector("#body");
            body.innerHTML = html
          });

          ctx.pushEvent("initial-render", { });

          ctx.handleSync(() => {
            // Synchronously invokes change listeners
            document.activeElement && document.activeElement.dispatchEvent(new Event("change"));
          });
        });
    }
    """
  end
end

Kino.SmartCell.register(Kino.TailwindPlayground)
Kino.nothing()
Dojo.PubSub.publish(
  "class:book1",
  {name,
   """
   
   
   
     
     
     
       @keyframes bounce {
         0%, 100% { transform: translateY(200px); }
         50% { transform: translateY(500px); }
       }
     
   
   
     
       

Hello from Acme!

Welcome to our magical world.

"""
} )
require Dojo.Module

# String.to_atom("Brit")

Dojo.Module.generate(name, "hellod")

# :erlang.binary_to_existing_atom("Elixir.Dojo.PubSub", :utf8)
# Module.con
Dojo.Mat.Brit.hello()