Added a new way to visualize raw binary data that may contain ASCII text, control characters and other nonprintables, for use in testing or debugging

### Design Goals ###
# The point of this code is to come up with a good visual representation/encoding of binary data that can be represented simply in a UTF-8 string;
# that is, the design priorities are:
# 1) visually distinct
# 2) conformant to printable ASCII 0-127 (so embedded text is instantly recognizable)
# 3) each representation is only the width of 1 character (although internally may be multibyte) so that printouts are as long as the
#    underlying byte length, but no longer; this made solutions like \n and whatnot infeasible
# 4) for control characters and nonprintable characters and values from 128-255, use a representation that is ideally only 2 bytes, but if no workable
#    substitute exists in the 2 byte Unicode character set, 3 bytes is "OK"
# 5) Easily copyable, pastable, and printable (possibly even OCR'able)
# 6) Less memory-consuming and more immediately useful (especially visually) than hexadecimal encoding
# 7) Ideally useful in debugging/testing environments but can also be used as a general binary representation in code (to be decoded right before use of course)
# 8) avoid use of emoji due to 4-byte requirement and "visually jarring"; so for example, this is not useful https://ayende.com/blog/177729/emoji-encoding-a-new-style-for-binary-encoding-for-the-web

defmodule PrintableBinary do

  def encode(0), do: "∅" # \0 or possibly ␀ but the spacing on that gets weird; see https://en.wikipedia.org/wiki/C0_and_C1_control_codes
  def encode(1), do: "¯" # Start of Heading
  def encode(2), do: "«" # Start of Text
  def encode(3), do: "»" # End of Text
  def encode(4), do: "ϟ" # control-D, or "end of transmission" signal. 3bytes: ⌁, 2bytes: ϟ
  def encode(5), do: "¿" # Enquiry (ENQ)
  def encode(6), do: "¡" # Acknowledge (ACK)
  def encode(7), do: "ª" # \a (bell). 2bytes: ª. 4 bytes: 🔔
  def encode(8), do: "⌫"  # \b (backspace). 3bytes: ⌫
  def encode(9), do: "⇥" # \t (tab). 3 bytes: ⇥
  def encode(10), do: "⇩" # \n (newline or line feed). 3bytes: ⇩
  def encode(11), do: "↧" # \v (vertical tab). 3bytes: ↧
  def encode(12), do: "§" # \f 2bytes: § (could also use ↡ for form feed/page break, but that takes 3 bytes and is less visually distinct)
  def encode(13), do: "⏎" # \r (carriage return). 3bytes: ⏎
  def encode(14), do: "ȯ" # Shift Out
  def encode(15), do: "ʘ" # Shift Back In
  def encode(16), do: "Ɣ" # Data Link Escape
  def encode(17), do: "¹" # (XON) Device Control 1
  def encode(18), do: "²" # Device Control 2
  def encode(19), do: "º" # (XOFF) Device Control 3
  def encode(20), do: "³" # Device Control 4 (used 3 since I wanted 0 for XOFF and using ⁴ is 3 bytes)
  def encode(21), do: "Ͷ" # Negative Acknowledge (NAK)
  def encode(22), do: "ɨ" # Synchronous Idle
  def encode(23), do: "¬" # End of Transmission Block
  def encode(24), do: "©" # Cancel (cancel previous input)
  def encode(25), do: "¦" # End of Medium
  def encode(26), do: "Ƶ" # control-Z, SIGTSTP/stop/suspend, "soft EOF", possibly consider 🛑 or ⏸? all 4 bytes tho
  def encode(27), do: "⎋" # \e (escape). 3 bytes: ⎋.
  def encode(28), do: "Ξ" # File Separator
  def encode(29), do: "ǁ" # Group Separator
  def encode(30), do: "ǀ" # Record Separator
  def encode(31), do: "¶" # Unit Separator

  # fallthrough to the 3 byte control character symbolic representations (hard to read/indistinct) when no clear 2-byte substitute provided
  # Note: This fallthrough isn't currently reachable because all the values are now accounted for above
  # but you can comment those out if you want this type of representation instead
  def encode(n) when is_integer(n) and n > -1 and n < 32 do
    <<(n + 9216)::utf8>>
  end

  # space. make it visible with a ␣. also prevents unwanted line breaks on actual spaces.
  def encode(32), do: "␣" # \s ?

  # encode double quote to utf8 757 so that it doesn't need to get escaped
  # I wanted something that looked enough like a double quote to be recognizable
  # but different enough to not be mistaken for the normal " character.
  def encode(34), do: "˵"

  # encode backslash to Ʌ so that it doesn't need to get escaped
  def encode(92), do: "Ʌ"

  def encode(n) when is_integer(n) and n > 32 and n < 127 do
    to_string([n])
  end

  # forward delete
  def encode(127), do: "⌦"

  # move encodings of Ø and ø (both 2 bytes) so that ∅ (3 bytes) is visually distinct for NULL
  def encode(152), do: "Ō"
  def encode(184), do: "ŏ"

  def encode(n) when is_integer(n) and n > 127 and n < 192 do
    <<195, n>>
  end

  def encode(n) when is_integer(n) and n > 191 and n < 256 do
    <<196, (n - 192) + 0x80>>
  end

  def encode(n) when is_integer(n) and n > 255 do
    raise "Invalid byte to encode: #{n}"
  end

  def encode(n) when is_list(n) do
    encode(codepoint_list_to_binary(n))
  end

  def encode(<<>>), do: ""
  def encode(<<c::8, rest::binary>>) do
    encode(c) <> encode(rest)
  end

  def to_bytelist(<<>>), do: []
  def to_bytelist(<<c::8, rest::binary>>) do
    [c | to_bytelist(rest)]
  end

  def codepoint_list_to_binary(list) when is_list(list) do
    do_codepoint_list_to_binary("", list)
  end
  defp do_codepoint_list_to_binary(bin, []), do: bin
  defp do_codepoint_list_to_binary(bin, [cp | lst]) when cp > -1 and cp < 256 do
    do_codepoint_list_to_binary(bin <> <<cp>>, lst)
  end

  @decode_charset "∅¯«»ϟ¿¡ª⌫⇥⇩↧§⏎ȯʘƔ¹²º³Ͷɨ¬©¦Ƶ⎋Ξǁǀ¶␣!˵#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[Ʌ]^_`abcdefghijklmnopqrstuvwxyz{|}~⌦ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ŌÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷ŏùúûüýþÿĀāĂăĄąĆćĈĉĊċČčĎďĐđĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħĨĩĪīĬĭĮįİıĲĳĴĵĶķĸĹĺĻļĽľĿ"
                  |> String.codepoints

  def decode(<<>>), do: ""
  # some UTF8 weirdness to hack around... possibly replace offending character, but this works for now
  def decode(<<n::utf8, bin::binary>>) when n == 65039, do: decode(bin)
  def decode(<<n::utf8, bin::binary>>) do
    code = Enum.find_index(@decode_charset, fn cs -> <<n::utf8>> == cs end)
    unless code do
      raise "Character #{inspect(<<n::utf8>>)} with codepoint #{n} and length #{byte_size(<<n::utf8>>)} was not in the decode list"
    end
    <<code>> <> decode(bin)
  end
  def decode(n) when is_list(n) do
    Enum.map(n, fn c -> decode(c) end)
  end
end

# run this inline suite with "elixir #{__ENV__.file} test"
if System.argv |> List.first == "test" do
  ExUnit.start

  defmodule PrintableBinaryTest do
    use ExUnit.Case, async: true
    alias PrintableBinary, as: PB

    # some helper funcs
    defp random_stream(min..max) when max >= min do
      max = max + 1
      seed = :rand.seed_s(:exsplus)
      Stream.unfold(seed, fn acc ->
        {next, acc} = :rand.uniform_s(acc)
        {trunc(min + (next * (max - min))), acc}
      end)
    end

    defp random_binary_data(len) do
      random_stream(0..255) |> Enum.take(len) |> PB.codepoint_list_to_binary
    end

    test "encoding control chars 0-32" do
      assert "∅¯«»ϟ¿¡ª⌫⇥⇩↧§⏎ȯʘƔ¹²º³Ͷɨ¬©¦Ƶ⎋Ξǁǀ¶␣" == (0..32) |> Enum.to_list |> PB.codepoint_list_to_binary |> PB.encode
    end

    test "encoding printable chars 33-127" do
      assert "!˵#$%&'()*+,-./0123456789:;<=>?@" == (33..64) |> Enum.to_list |> to_string |> PB.encode
      assert "ABCDEFGHIJKLMNOPQRSTUVWXYZ[Ʌ]^_`abcdefghijklmnopqrstuvwxyz{|}~⌦" == (65..127) |> Enum.to_list |> PB.codepoint_list_to_binary |> PB.encode
    end

    test "encoding 128-191" do
      assert "ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ŌÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷ŏùúûüýþÿ" = (128..191) |> Enum.to_list |> PB.codepoint_list_to_binary |> PB.encode
    end

    test "encoding 192-255" do
      assert "ĀāĂăĄąĆćĈĉĊċČčĎďĐđĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħĨĩĪīĬĭĮįİıĲĳĴĵĶķĸĹĺĻļĽľĿ" = (192..255) |> Enum.to_list |> PB.codepoint_list_to_binary |> PB.encode
    end

    test "making visible some text within some binary data" do
      prefix = random_binary_data(10)
      suffix = random_binary_data(10)
      test_binary = prefix <> "there once was a man in München\r\n" <> suffix
      # There's still an issue with cursor placement/spacing using this encoding, at least in my editor...
      # Tabling for now
      assert PB.encode(prefix) <> "there␣once␣was␣a␣man␣in␣Măünchen⏎⇩" <> PB.encode(suffix) == PB.encode(test_binary)
    end

    test "all encodings are unique" do
      all_symbols = (0..255) |> Enum.to_list |> PB.codepoint_list_to_binary |> PB.encode |> String.split("", trim: true)
      assert 256 == all_symbols |> Enum.uniq |> length
    end

    test "encoding and then decoding random binary result gives same argument" do
      charlist = random_stream(0..255) |> Enum.take(2000)
      charlist_as_binary = PB.codepoint_list_to_binary(charlist)
      assert charlist_as_binary == charlist |> PB.encode |> PB.decode
      assert charlist_as_binary == charlist_as_binary |> PB.encode |> PB.decode
      # IO.inspect byte_size(bin |> PB.encode) # ~67% expansion in size for random binary data, reasonable?
    end

    test "encoding problematic binaries doesn't raise" do
      PrintableBinary.encode(<<198, 181, 239, 184, 143>>)
    end

  end
end

error: pathspec 'printable_binary.exs' did not match any file(s) known to git


Add a wrapper for the Users entity

Add a wrapper for the Users entity

defmodule HardHat.Users do
  @moduledoc """
  A wrapper for the Users entity.

  https://docs.travis-ci.com/api/#users
  """

  import HardHat
  alias HardHat.Client

  @doc """
  Show the authenticated user.

  ## Examples

      HardHat.Users.whoami(client)
  """
  @spec whoami(Client.t) :: HardHat.response
  def whoami(client) do
    get(client, "users")
  end

  @doc """
  Show the user identified by `id`.

  ## Examples

      HardHat.Users.show(client, 267)
  """
  @spec show(Client.t, pos_integer) :: HardHat.response
  def show(client, id) do
    get(client, "users/#{id}")
  end

  @doc """
  Trigger a new sync with GitHub.

  ## Examples

      HardHat.Users.sync(client)
  """
  @spec sync(Client.t) :: HardHat.response
  def sync(client) do
    post(client, "users/sync")
  end
end

error: pathspec 'apps/hard_hat/lib/hard_hat/users.ex' did not match any file(s) known to git


Add internal release task

Add internal release task

defmodule Mix.Tasks.Conform.Release do
  @moduledoc """
  This is an internal mix task, meant to be consumed via exrm. Do not use.
  """
  @shortdoc false

  use Mix.Task

  def run(_) do
    conform_path = Path.join([__DIR__, "..", "..", ".."]) |> Path.expand
    escript_path = Path.join(conform_path, "conform")
    current_path = File.cwd!
    # Switch to conform directory
    File.cd! conform_path
    # Run escript task
    result = case Mix.Shell.cmd("mix escriptize", fn _ -> nil end) do
      0 -> escript_path
      _ -> {:error, "Failed to generate escript."}
    end
    File.cd! current_path
    result
  end
end

error: pathspec 'lib/mix/tasks/conform.release.ex' did not match any file(s) known to git


Test Storage endpoint with Server endpoint.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/evercam/evercam-admin.git/'


Struct 2

Struct 2

defprotocol Valid do
  @doc "Returns true if data is considered nominally valid"
  def valid?(data)
end

defmodule Planemo do
  defstruct name: :nil, gravity: 0, diameter: 0, distance_from_sun: 0
end
defimpl Valid, for: Planemo do
  def valid?(p) do
    p.gravity >= 0 && p.diameter >= 0 &&
    p.distance_from_sun >= 0
  end
end

p = %Planemo{} # %Planemo{diameter: 0, distance_from_sun: 0, gravity: 0, name: nil}
IO.inspect Valid.valid?(p) # true
p2 = %Planemo{name: :weirdworld, gravity: -2.3} # %Planemo{diameter: 0, distance_from_sun: 0, gravity: -2.3, name: :weirdworld}
IO.inspect Valid.valid?(p2) # false
IO.inspect p2

defmodule Tower do
  defstruct location: "", height: 20, planemo: :earth, name: ""
end
defimpl Valid, for: Tower do
  def valid?(%Tower{height: h, planemo: p}) do
    h >= 0 && p != nil
  end
end
defimpl Inspect, for: Tower do
  import Inspect.Algebra
  def inspect(item, _options) do
    metres = concat(to_string(item.height), "m:")
    msg = concat([metres, break, item.name, ",", break, item.location, ",", break,to_string(item.planemo)])
  end
end

t = %Tower{}
IO.inspect Valid.valid?(t) # true
t2 = %Tower{height: -2, location: "underground"} # %Tower{height: -2, location: "underground", name: "", planemo: :earth}
IO.inspect Valid.valid?(t2)  # "241m: Woolworth Building, NYC, earth"
IO.inspect t2

error: pathspec 'other/structs-2.ex' did not match any file(s) known to git


Test changeset view

Test changeset view

defmodule CodeCorps.ChangesetViewTest do
  use CodeCorps.ConnCase, async: true

  alias CodeCorps.Preview

  import Phoenix.View, only: [render: 3]

  test "renders all errors properly" do
    changeset = Preview.create_changeset(%Preview{}, %{})

    rendered_json = render(CodeCorps.ChangesetView, "error.json-api", %{changeset: changeset})

    expected_json = %{
      errors: [
        %{
          id: "VALIDATION_ERROR",
          detail: "can't be blank",
          source: %{
            pointer: "data/attributes/markdown"
          },
          status: 422
        },
        %{
          id: "VALIDATION_ERROR",
          detail: "can't be blank",
          source: %{
            pointer: "data/attributes/user_id"
          },
          status: 422
        }
      ]
    }

    assert rendered_json == expected_json
  end
end

error: pathspec 'test/views/changeset_view_test.exs' did not match any file(s) known to git


Pass camera around instead of exid

Pass camera around instead of exid

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/evercam/evercam-media.git/'


refactor user controller

refactor user controller


Add Runtime config

Add Runtime config

import Config

# config/runtime.exs is executed for all environments, including
# during releases. It is executed after compilation and before the
# system starts, so it is typically used to load production configuration
# and secrets from environment variables or elsewhere. Do not define
# any compile-time configuration in here, as it won't be applied.
# The block below contains prod specific runtime configuration.

# Start the phoenix server if environment is set and running in a release
if System.get_env("PHX_SERVER") && System.get_env("RELEASE_NAME") do
  config :chess, ChessWeb.Endpoint, server: true
end

if config_env() == :prod do
  # The secret key base is used to sign/encrypt cookies and other secrets.
  # A default value is used in config/dev.exs and config/test.exs but you
  # want to use a different value for prod and you most likely don't want
  # to check this value into version control, so we use an environment
  # variable instead.
  secret_key_base =
    System.get_env("SECRET_KEY_BASE") ||
      raise """
      environment variable SECRET_KEY_BASE is missing.
      You can generate one by calling: mix phx.gen.secret
      """

  host = System.get_env("PHX_HOST") || "example.com"
  port = String.to_integer(System.get_env("PORT") || "4000")

  config :chess, ChessWeb.Endpoint,
    url: [host: host, port: 443],
    http: [
      # Enable IPv6 and bind on all interfaces.
      # Set it to  {0, 0, 0, 0, 0, 0, 0, 1} for local network only access.
      # See the documentation on https://hexdocs.pm/plug_cowboy/Plug.Cowboy.html
      # for details about using IPv6 vs IPv4 and loopback vs public addresses.
      ip: {0, 0, 0, 0, 0, 0, 0, 0},
      port: port
    ],
    secret_key_base: secret_key_base

  # ## Using releases
  #
  # If you are doing OTP releases, you need to instruct Phoenix
  # to start each relevant endpoint:
  #
  #     config :<%= @web_app_name %>, <%= @endpoint_module %>, server: true
  #
  # Then you can assemble a release by calling `mix release`.
  # See `mix help release` for more information.<%= if @mailer do %>

  # ## Configuring the mailer
  #
  # In production you need to configure the mailer to use a different adapter.
  # Also, you may need to configure the Swoosh API client of your choice if you
  # are not using SMTP. Here is an example of the configuration:
  #
  #     config :<%= @app_name %>, <%= @app_module %>.Mailer,
  #       adapter: Swoosh.Adapters.Mailgun,
  #       api_key: System.get_env("MAILGUN_API_KEY"),
  #       domain: System.get_env("MAILGUN_DOMAIN")
  #
  # For this example you need include a HTTP client required by Swoosh API client.
  # Swoosh supports Hackney and Finch out of the box:
  #
  #     config :swoosh, :api_client, Swoosh.ApiClient.Hackney
  #
  # See https://hexdocs.pm/swoosh/Swoosh.html#module-installation for details.<% end %>
end

error: pathspec 'config/runtime.exs' did not match any file(s) known to git


Add telegram module to send offers there

defmodule ElixirJobsWeb.Telegram do
  @moduledoc """
  Module to send new elixir job offers to telegram channel.
  """

  alias ElixirJobs.Offers.Offer
  alias ElixirJobsWeb.Router.Helpers, as: Routehelpers
  alias ElixirJobsWeb.HumanizeHelper
  alias ElixirJobsWeb.Gettext

  require ElixirJobsWeb.Gettext

  def send(%Plug.Conn{} = conn, %Offer{} = offer) do
    channel = Application.get_env(:elixir_jobs, :telegram_channel, "")
    send(conn, offer, channel)
  end

  def send(_, _, ""), do: :ok

  def send(%Plug.Conn{} = conn, %Offer{} = offer, channel) do
    job_type = HumanizeHelper.human_get_type(offer.job_type, Gettext.gettext("Unknown"))
    job_place = HumanizeHelper.human_get_place(offer.job_place, Gettext.gettext("Unknown"))

    text = """
    *#{offer.title}*
    #{offer.company} (#{offer.location})
    #{job_type} - #{job_place}
    #{Routehelpers.offer_url(conn, :show, offer.slug)}
    """

    case Nadia.send_message("@#{channel}", text, parse_mode: "Markdown") do
      {:ok, _result} ->
        :ok

      error ->
        error
    end
  end
end

error: pathspec 'lib/elixir_jobs_web/telegram.ex' did not match any file(s) known to git


Simple test for Top module

Simple test for Top module

defmodule Phobs.TopChannel.Top.Test do
  use ExUnit.Case
  alias Phobs.TopChannel.Top

  test "it returns an Enumerable of processes" do
    Top.top
    |> Enum.each fn proc -> assert proc.pid end
  end
end

error: pathspec 'test/channels/top_test.exs' did not match any file(s) known to git


Increment version [ci skip]

Increment version [ci skip]

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/edenlabllc/ehealth.api.git/'


Increment version [ci skip]

Increment version [ci skip]


Added cache invalidation for camera by owner

defmodule EvercamMedia.Cache do
  alias EvercamMedia.Repo

  def invalidate_for_user(username) do
    list = ["true", "false", ""]
    permute(username, list, "", 1)
  end

  def invalidate_for_camera(camera_exid) do
    camera = Repo.one! Camera.by_exid_with_owner(camera_exid)
    invalidate_for_user(camera.owner.username)
  end

  defp permute(username, list, _, 1) do
    Enum.each list, &permute(username, list, &1, 0)
  end

  defp permute(username, list, key, 0) do
    Enum.each list, &delete_cache("cameras|#{username}|#{&1}|#{key}")
  end

  defp delete_cache(key) do
    IO.inspect key
    :mcd.delete(:memcached, key)
  end
end

error: pathspec 'lib/media/cache.ex' did not match any file(s) known to git


Tidy up cleanup module

Tidy up cleanup module


Extract a function for listing camera apps stored in seaweedfs


val not used

val not used

defmodule Solution do
  def main() do
    a = IO.get("") |> String.strip |> String.to_integer
    b = IO.get("") |> String.strip |> String.to_list
    IO.puts b
  end
end

Solution.main()

error: pathspec 'elixir/100.exs' did not match any file(s) known to git


Use Elixir Base native url_encode and url_decode functions

defmodule Joken.Utils do
  alias :jsx, as: JSON
  @moduledoc false

  def to_map({:ok, keywords}), do: {:ok, keywords |> Enum.into(%{})}
  def to_map(error), do: error

  def get_data(jwt) do
    values = String.split(jwt, ".")
    split_count = Enum.count(values)

    if split_count < 2 or split_count > 3 do
      {:error, "Invalid JSON Web Token"}
    else
      decoded_data = Enum.map_reduce(values, 0, fn(x, acc) ->
        if acc < 2 do
            data = base64url_decode(x)
            map = JSON.decode(data) |> Enum.map(fn({k, v}) -> {String.to_atom(k), v} end)
            { map , acc + 1}
        else
            {x, acc + 1}
        end
      end)
      {decoded, _} = decoded_data
      {:ok, decoded}
    end
  end

  def base64url_encode(data) do
    data |> Base.url_encode64 |> String.rstrip(?=)
  end

  def base64url_decode(data) do
    info = data <> case rem(byte_size(data),4) do
      2 -> "=="
      3 -> "="
      _ -> ""
    end
    Base.url_decode64!(info)
  end
end

defmodule Joken.Utils do
  alias :jsx, as: JSON
  @moduledoc false

  def to_map({:ok, keywords}), do: {:ok, keywords |> Enum.into(%{})}
  def to_map(error), do: error

  def get_data(jwt) do
    values = String.split(jwt, ".")
    split_count = Enum.count(values)

    if split_count < 2 or split_count > 3 do
      {:error, "Invalid JSON Web Token"}
    else
      decoded_data = Enum.map_reduce(values, 0, fn(x, acc) ->
        if acc < 2 do
            data = base64url_decode(x)
            map = JSON.decode(data) |> Enum.map(fn({k, v}) -> {String.to_atom(k), v} end)
            { map , acc + 1}
        else
            {x, acc + 1}
        end
      end)
      {decoded, _} = decoded_data
      {:ok, decoded}
    end
  end

  def base64url_encode(data) do
    data
    |> :base64.encode_to_string
    |> to_string
    |> String.replace(~r/[\n\=]/, "")
    |> String.replace(~r/\+/, "-")
    |> String.replace(~r/\//, "_")
  end

  def base64url_decode(data) do
    base64_bin = String.replace(data, "-", "+") |> String.replace("_", "/")
    base64_bin = base64_bin <> case rem(byte_size(base64_bin),4) do
      2 -> "=="
      3 -> "="
      _ -> ""
    end

    :base64.decode_to_string(base64_bin) |> to_string
  end
end


Improve query performance by filtering preloaded access rights


Increment version [ci skip]

Increment version [ci skip]

fatal: unable to access 'https://github.com/edenlabllc/ehealth.api.git/': The requested URL returned error: 403


Bump version to 0.8.4

Bump version to 0.8.4

fatal: unable to access 'https://github.com/preciz/insta_scrapex.git/': The requested URL returned error: 403


bumps version to v0.1.0-dev

bumps version to v0.1.0-dev

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/lookuppm/package_finder.git/'


adds coverage for attendance_view

adds coverage for attendance_view

fatal: unable to access 'https://github.com/digitalnatives/course_planner.git/': The requested URL returned error: 403


Bump version

Bump version

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/preciz/insta_scrapex.git/'


Created ffmpeg wrapper

Created ffmpeg wrapper

fatal: unable to access 'https://github.com/elarkham/animu.git/': The requested URL returned error: 403


Create mix.exs

Create mix.exs

defmodule Dynamite.Mixfile do
  use Mix.Project

  def project do
    [app: :dynamite,
     version: "0.0.1",
     elixir: "> 1.0.0",
     deps: deps]
  end

  def application do
    [ applications: [:couchbeam, :cowboy, :ranch, :httpoison],
      env: [routing_table: []],
      mod: { Dynamite, [] }
    ]
  end

  defp deps do
    [ { :cowboy, "> 1.0.0" },
      { :couchbeam, git: "git://github.com/benoitc/couchbeam.git", tag: "master"},
			{ :poison, "~> 1.5" },
			{ :httpoison, "> 0.8.0" }]
  end
end

error: pathspec 'mix.exs' did not match any file(s) known to git


a better dyson solution

a better dyson solution

fatal: unable to access 'https://github.com/codecakes/elixir_days.git/': The requested URL returned error: 403


Macro-tize command parser tests

Macro-tize command parser tests

fatal: unable to access 'https://github.com/pviafore/warlight2-starter-bot-elixir.git/': The requested URL returned error: 403


Fixes typo.

Fixes typo.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/futhr/fux.git/'


Increment version [ci skip]

Increment version [ci skip]


test FilteringHelperTest with LegalEntity


Return empty list of share requests when user doesn't have rights

fatal: unable to access 'https://github.com/evercam/evercam-media.git/': The requested URL returned error: 403


fixes path to discovery app

fixes path to discovery app

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/elixytics/monolith.git/'


Adding reload to iex

Adding reload to iex

defmodule R do
  def r do
    Mix.Task.reenable "compile.elixir"
    Application.stop(Mix.Project.config[:app])
    Mix.Task.run "compile.elixir"
    Application.start(Mix.Project.config[:app], :permanent)
  end
end

error: pathspec '.iex.exs' did not match any file(s) known to git


Updated mix.exs file

Updated mix.exs file

fatal: unable to access 'https://github.com/riverrun/openmaize-phoenix.git/': The requested URL returned error: 403


Increment version [ci skip]

Increment version [ci skip]

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/edenlabllc/ehealth.api.git/'


Revert "Schedule snapshot cleanup to run at midnight"

This reverts commit 9025327dbb968323fbf73c67d2d6b9438906c7d7.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/evercam/evercam-media.git/'


config: added MontrealElixir module file to keep contexts in

defmodule MontrealElixir do
  @moduledoc """
  MontrealElixir keeps the contexts that define your domain
  and business logic.

  Contexts are also responsible for managing your data, regardless
  if it comes from the database, an external API or others.
  """
end

error: pathspec 'apps/montreal_elixir/lib/montreal_elixir.ex' did not match any file(s) known to git


Test list_prefixes/2

Test list_prefixes/2


Moving custom strategy to use helpers on get number of wastelands

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/pviafore/warlight2-ai-bot-elixir.git/'


Simple chat room actor

Simple chat room actor

defmodule FtChat.ChatRoom do

    defmodule ChatRoomState do
        defstruct [:name, :users]
    end

    use GenServer

    def start_link(name) do
        GenServer.start_link __MODULE__, name
    end

    def join(chat_room, user) do
        GenServer.cast chat_room, {:join, user}
    end

    def leave(chat_room, user) do
        GenServer.cast chat_room, {:leave, user}
    end

    def post(chat_room, message) do
        GenServer.cast chat_room, {:post, message}
    end

    def init(name) do
        {:ok, %ChatRoomState{
            name: name,
            users: HashSet.new
        }}
    end

    def handle_cast({:join, user}, st) do
        st = %{ st | users: HashSet.put(st.users, user) }
        {:noreply, st}
    end

    def handle_cast({:leave, user}, st) do
        st = %{ st | users: HashSet.delete(st.users, user) }
        {:noreply, st}
    end

    def handle_cast({:post, message}, st) do
        Enum.each st.users &(send &1, {:chat_message, st.name, message})
        {:noreply, st}
    end
end

error: pathspec 'lib/chat_room.ex' did not match any file(s) known to git


Fixed memory leak

Fixed memory leak

defmodule EvercamMedia.Worker do
  import EvercamMedia.Snapshot
  import EvercamMedia.Schedule

  def start_link(args) do
    IO.puts("Starting camera worker '#{args[:camera_id]}'")
    worker_name = args[:camera_id] |> String.to_atom
    GenServer.start_link(__MODULE__, args, name: worker_name)
  end

  def init(args) do
    Task.start_link(fn -> loop(args) end)
  end

  defp loop(args) do
    if args[:frequent] do
      :timer.sleep(1000)
    else
      :timer.sleep(60_000 + args[:initial_sleep])
      args = Dict.put(args, :initial_sleep, 0)
    end
    if scheduled?(args[:schedule], args[:timezone]) do
      Task.async(fn -> check_camera(args) end) |> Task.await(30_000)
    end
    loop(args)
  end
end

defmodule EvercamMedia.Worker do
  import EvercamMedia.Snapshot
  import EvercamMedia.Schedule

  def start_link(args) do
    IO.puts("Starting camera worker '#{args[:camera_id]}'")
    worker_name = args[:camera_id] |> String.to_atom
    GenServer.start_link(__MODULE__, args, name: worker_name)
  end

  def init(args) do
    Task.start_link(fn -> loop(args) end)
  end

  defp loop(args) do
    if args[:frequent] do
      :timer.sleep(1000)
    else
      :timer.sleep(60_000 + args[:initial_sleep])
      args = Dict.put(args, :initial_sleep, 0)
    end
    if scheduled?(args[:schedule], args[:timezone]) do
      Task.async(fn -> check_camera(args) end)
    end
    loop(args)
  end
end


remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/sharkspeed/dororis.git/'


Fix tests after the rebase.

Fix tests after the rebase.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/BrainMaestro/elixir-phoenix-realworld.git/'


Move snapmails to S3. (#913)

Move snapmails to S3. (#913)


Remove obsolete Storage functions

Remove obsolete Storage functions


Update Router docs to make paths consistent

defmodule Phoenix.Router do
  defmodule NoRouteError do
    @moduledoc """
    Exception raised when no route is found.
    """
    defexception plug_status: 404, message: "no route found", conn: nil, router: nil

    def exception(opts) do
      conn   = Keyword.fetch!(opts, :conn)
      router = Keyword.fetch!(opts, :router)
      path   = "/" <> Enum.join(conn.path_info, "/")

      %NoRouteError{message: "no route found for #{conn.method} #{path} (#{inspect router})",
                    conn: conn, router: router}
    end
  end

  @moduledoc """
  Defines a Phoenix router.

  The router provides a set of macros for generating routes
  that dispatch to specific controllers and actions. Those
  macros are named after HTTP verbs. For example:

      defmodule MyApp.Router do
        use Phoenix.Router

        get "/pages/:page", PageController, :show
      end

  The `get/3` macro above accepts a request of format `"/pages/VALUE"` and
  dispatches it to the show action in the `PageController`.

  Routes can also match glob-like patterns, routing any path with a common
  base to the same controller. For example:

      get "/dynamic*anything", DynamicController, :show

  Phoenix's router is extremely efficient, as it relies on Elixir
  pattern matching for matching routes and serving requests.

  ### Helpers

  Phoenix automatically generates a module `Helpers` inside your router
  which contains named helpers to help developers generate and keep
  their routes up to date.

  Helpers are automatically generated based on the controller name.
  For example, the route:

      get "/pages/:page", PageController, :show

  will generate the following named helper:

      MyApp.Router.Helpers.page_path(conn_or_endpoint, :show, "hello")
      "/pages/hello"

      MyApp.Router.Helpers.page_path(conn_or_endpoint, :show, "hello", some: "query")
      "/pages/hello?some=query"

      MyApp.Router.Helpers.page_url(conn_or_endpoint, :show, "hello")
      "http://example.com/pages/hello"

      MyApp.Router.Helpers.page_url(conn_or_endpoint, :show, "hello", some: "query")
      "http://example.com/pages/hello?some=query"

  The url generated in the named url helpers is based on the configuration for
  `:url`, `:http` and `:https`.

  The named helper can also be customized with the `:as` option. Given
  the route:

      get "/pages/:page", PageController, :show, as: :special_page

  the named helper will be:

      MyApp.Router.Helpers.special_page_path(conn, :show, "hello")
      "/pages/hello"

  ### Scopes and Resources

  The router also supports scoping of routes:

      scope "/api/v1", as: :api_v1 do
        get "/pages/:id", PageController, :show
      end

  For example, the route above will match on the path `"/api/v1/pages/:id"`
  and the named route will be `api_v1_page_path`, as expected from the
  values given to `scope/2` option.

  Phoenix also provides a `resources/4` macro that allows developers
  to generate "RESTful" routes to a given resource:

      defmodule MyApp.Router do
        use Phoenix.Router

        resources "/pages", PageController, only: [:show]
        resources "/users", UserController, except: [:delete]
      end

  Finally, Phoenix ships with a `mix phoenix.routes` task that nicely
  formats all routes in a given router. We can use it to verify all
  routes included in the router above:

      $ mix phoenix.routes
      page_path  GET    /pages/:id       PageController.show/2
      user_path  GET    /users           UserController.index/2
      user_path  GET    /users/:id/edit  UserController.edit/2
      user_path  GET    /users/new       UserController.new/2
      user_path  GET    /users/:id       UserController.show/2
      user_path  POST   /users           UserController.create/2
      user_path  PATCH  /users/:id       UserController.update/2
                 PUT    /users/:id       UserController.update/2

  One can also pass a router explicitly as an argument to the task:

      $ mix phoenix.routes MyApp.Router

  Check `scope/2` and `resources/4` for more information.

  ## Pipelines and plugs

  Once a request arrives at the Phoenix router, it performs
  a series of transformations through pipelines until the
  request is dispatched to a desired end-point.

  Such transformations are defined via plugs, as defined
  in the [Plug](http://github.com/elixir-lang/plug) specification.
  Once a pipeline is defined, it can be piped through per scope.

  For example:

      defmodule MyApp.Router do
        use Phoenix.Router

        pipeline :browser do
          plug :fetch_session
          plug :accepts, ["html"]
        end

        scope "/" do
          pipe_through :browser

          # browser related routes and resources
        end
      end

  `Phoenix.Router` imports functions from both `Plug.Conn` and `Phoenix.Controller`
  to help define plugs. In the example above, `fetch_session/2`
  comes from `Plug.Conn` while `accepts/2` comes from `Phoenix.Controller`.

  Note that router pipelines are only invoked after a route is found.
  No plug is invoked in case no matches were found.

  """

  alias Phoenix.Router.Resource
  alias Phoenix.Router.Scope
  alias Phoenix.Router.Route
  alias Phoenix.Router.Helpers

  @http_methods [:get, :post, :put, :patch, :delete, :options, :connect, :trace, :head]

  @doc false
  defmacro __using__(_) do
    quote do
      unquote(prelude())
      unquote(defs())
      unquote(match_dispatch())
    end
  end

  defp prelude() do
    quote do
      Module.register_attribute __MODULE__, :phoenix_routes, accumulate: true
      @phoenix_forwards %{}

      import Phoenix.Router
      import Plug.Conn
      import Phoenix.Controller

      # Set up initial scope
      @phoenix_pipeline nil
      Phoenix.Router.Scope.init(__MODULE__)
      @before_compile unquote(__MODULE__)
    end
  end

  # Because those macros are executed multiple times,
  # we end-up generating a huge scope that drastically
  # affects compilation. We work around it by defining
  # those functions only once and calling it over and
  # over again.
  defp defs() do
    quote unquote: false do
      var!(add_resources, Phoenix.Router) = fn resource ->
        path = resource.path
        ctrl = resource.controller
        opts = resource.route

        if !resource.singleton do
          param = resource.param

          Enum.each resource.actions, fn
            :index   -> get    path,                             ctrl, :index, opts
            :show    -> get    path <> "/:" <> param,            ctrl, :show, opts
            :new     -> get    path <> "/new",                   ctrl, :new, opts
            :edit    -> get    path <> "/:" <> param <> "/edit", ctrl, :edit, opts
            :create  -> post   path,                             ctrl, :create, opts
            :delete  -> delete path <> "/:" <> param,            ctrl, :delete, opts
            :update  ->
              patch path <> "/:" <> param, ctrl, :update, opts
              put   path <> "/:" <> param, ctrl, :update, Keyword.put(opts, :as, nil)
          end
        else
          Enum.each resource.actions, fn
            :show    -> get    path,            ctrl, :show, opts
            :new     -> get    path <> "/new",  ctrl, :new, opts
            :edit    -> get    path <> "/edit", ctrl, :edit, opts
            :create  -> post   path,            ctrl, :create, opts
            :delete  -> delete path,            ctrl, :delete, opts
            :update  ->
              patch path, ctrl, :update, opts
              put   path, ctrl, :update, Keyword.put(opts, :as, nil)
          end
        end
      end
    end
  end

  defp match_dispatch() do
    quote location: :keep do
      @behaviour Plug

      @doc """
      Callback required by Plug that initializes the router
      for serving web requests.
      """
      def init(opts) do
        opts
      end

      @doc """
      Callback invoked by Plug on every request.
      """
      def call(conn, opts), do: do_call(conn, opts)

      defp match_route(conn, []) do
        match_route(conn, conn.method, Enum.map(conn.path_info, &URI.decode/1), conn.host)
      end

      defp dispatch(conn, []) do
        try do
          conn.private.phoenix_route.(conn)
        catch
          kind, reason ->
            Plug.Conn.WrapperError.reraise(conn, kind, reason)
        end
      end

      defoverridable [init: 1, call: 2]
    end
  end

  @doc false
  defmacro __before_compile__(env) do
    routes = env.module |> Module.get_attribute(:phoenix_routes) |> Enum.reverse
    routes_with_exprs = Enum.map(routes, &{&1, Route.exprs(&1)})

    Helpers.define(env, routes_with_exprs)
    matches = Enum.map(routes_with_exprs, &build_match/1)

    plugs = [{:dispatch, [], true}, {:match_route, [], true}]
    {conn, pipeline} = Plug.Builder.compile(env, plugs, [])

    call =
      quote do
        unquote(conn) =
          update_in unquote(conn).private,
            &(&1 |> Map.put(:phoenix_pipelines, [])
                 |> Map.put(:phoenix_router, __MODULE__)
                 |> Map.put(__MODULE__, {unquote(conn).script_name, @phoenix_forwards}))
        unquote(pipeline)
      end

    # line: -1 is used here to avoid warnings if forwarding to root path
    match_404 =
      quote line: -1 do
        defp match_route(conn, _method, _path_info, _host) do
          raise NoRouteError, conn: conn, router: __MODULE__
        end
      end

    quote do
      defp do_call(unquote(conn), opts) do
        unquote(call)
      end

      @doc false
      def __routes__,  do: unquote(Macro.escape(routes))

      @doc false
      def __helpers__, do: __MODULE__.Helpers

      unquote(matches)
      unquote(match_404)
    end
  end

  defp build_match({_route, exprs}) do
    quote do
      defp match_route(var!(conn), unquote(exprs.verb_match), unquote(exprs.path),
                 unquote(exprs.host)) do
        unquote(exprs.dispatch)
      end
    end
  end

  @doc """
  Generates a route match based on an arbitrary HTTP method

  Useful for defining routes not included in the builtin macros:

  #{Enum.map_join(@http_methods, ", ", &"`#{&1}`")}

  ## Examples

      match(:move, "/events/:id", EventController, :move)

  """
  defmacro match(verb, path, plug, plug_opts, options \\ []) do
    add_route(:match, verb, path, plug, plug_opts, options)
  end

  for verb <- @http_methods do
    @doc """
    Generates a route to handle a #{verb} request to the given path.
    """
    defmacro unquote(verb)(path, plug, plug_opts, options \\ []) do
      verb = unquote(verb)
      quote bind_quoted: binding do
        match(verb, path, plug, plug_opts, options)
      end
    end
  end

  defp add_route(kind, verb, path, plug, plug_opts, options) do
    quote do
      @phoenix_routes Scope.route(__MODULE__, unquote(kind), unquote(verb), unquote(path),
                                  unquote(plug), unquote(plug_opts), unquote(options))
    end
  end

  @doc """
  Defines a plug pipeline.

  Pipelines are defined at the router root and can be used
  from any scope.

  ## Examples

      pipeline :api do
        plug :token_authentication
        plug :dispatch
      end

  A scope may then use this pipeline as:

      scope "/" do
        pipe_through :api
      end

  Every time `pipe_through/1` is called, the new pipelines
  are appended to the ones previously given.
  """
  defmacro pipeline(plug, do: block) do
    block =
      quote do
        plug = unquote(plug)
        @phoenix_pipeline []
        unquote(block)
      end

    compiler =
      quote unquote: false do
        Scope.pipeline(__MODULE__, plug)
        {conn, body} = Plug.Builder.compile(__ENV__, @phoenix_pipeline, [])
        defp unquote(plug)(unquote(conn), _) do
          try do
            unquote(body)
          catch
            kind, reason ->
              Plug.Conn.WrapperError.reraise(unquote(conn), kind, reason)
          end
        end
        @phoenix_pipeline nil
      end

    quote do
      try do
        unquote(block)
        unquote(compiler)
      after
        :ok
      end
    end
  end

  @doc """
  Defines a plug inside a pipeline.

  See `pipeline/2` for more information.
  """
  defmacro plug(plug, opts \\ []) do
    quote do
      if pipeline = @phoenix_pipeline do
        @phoenix_pipeline [{unquote(plug), unquote(opts), true}|pipeline]
      else
        raise "cannot define plug at the router level, plug must be defined inside a pipeline"
      end
    end
  end

  @doc """
  Defines a pipeline to send the connection through.

  See `pipeline/2` for more information.
  """
  defmacro pipe_through(pipes) do
    quote do
      if pipeline = @phoenix_pipeline do
        raise "cannot pipe_through inside a pipeline"
      else
        Scope.pipe_through(__MODULE__, unquote(pipes))
      end
    end
  end

  @doc """
  Defines "RESTful" routes for a resource.

  The given definition:

      resources "/users", UserController

  will include routes to the following actions:

    * `GET /users` => `:index`
    * `GET /users/new` => `:new`
    * `POST /users` => `:create`
    * `GET /users/:id` => `:show`
    * `GET /users/:id/edit` => `:edit`
    * `PATCH /users/:id` => `:update`
    * `PUT /users/:id` => `:update`
    * `DELETE /users/:id` => `:delete`

  ## Options

  This macro accepts a set of options:

    * `:only` - a list of actions to generate routes for, for example: `[:show, :edit]`
    * `:except` - a list of actions to exclude generated routes from, for example: `[:delete]`
    * `:param` - the name of the paramter for this resource, defaults to `"id"`
    * `:name` - the prefix for this resource. This is used for the named helper
      and as the prefix for the parameter in nested resources. The default value
      is automatically derived from the controller name, i.e. `UserController` will
      have name `"user"`
    * `:as` - configures the named helper exclusively
    * `:singleton` - defines routes for a singleton resource that is looked up by
      the client without referencing an ID. Read below for more information

  ## Singleton resources

  When a resource needs to be looked up without referencing an ID, because
  it contains only a single entry in the given context, the `:singleton`
  option can be used to generate a set of routes that are specific to
  such single resource:

    * `GET /user` => `:show`
    * `GET /user/new` => `:new`
    * `POST /user` => `:create`
    * `GET /user/edit` => `:edit`
    * `PATCH /user` => `:update`
    * `PUT /user` => `:update`
    * `DELETE /user` => `:delete`

    Usage example:

      `resources "/account", AccountController, only: [:show], singleton: true`

  """
  defmacro resources(path, controller, opts, do: nested_context) do
    add_resources path, controller, opts, do: nested_context
  end

  @doc """
  See `resources/4`.
  """
  defmacro resources(path, controller, do: nested_context) do
    add_resources path, controller, [], do: nested_context
  end

  @doc """
  See `resources/4`.
  """
  defmacro resources(path, controller, opts) do
    add_resources path, controller, opts, do: nil
  end

  @doc """
  See `resources/4`.
  """
  defmacro resources(path, controller) do
    add_resources path, controller, [], do: nil
  end

  defp add_resources(path, controller, options, do: context) do
    scope =
      if context do
        quote do
          scope resource.member, do: unquote(context)
        end
      end

    quote do
      resource = Resource.build(unquote(path), unquote(controller), unquote(options))
      var!(add_resources, Phoenix.Router).(resource)
      unquote(scope)
    end
  end

  @doc """
  Defines a scope in which routes can be nested.

  ## Examples

      scope "/api/v1", as: :api_v1, alias: API.V1 do
        get "/pages/:id", PageController, :show
      end

  The generated route above will match on the path `"/api/v1/pages/:id"`
  and will dispatch to `:show` action in `API.V1.PageController`. A named
  helper `api_v1_page_path` will also be generated.

  ## Options

  The supported options are:

    * `:path` - a string containing the path scope
    * `:as` - a string or atom containing the named helper scope
    * `:alias` - an alias (atom) containing the controller scope
    * `:host` - a string containing the host scope, or prefix host scope,
      ie `"foo.bar.com"`, `"foo."`
    * `:private` - a map of private data to merge into the connection when a route matches
    * `:assigns` - a map of data to merge into the connection when a route matches

  """
  defmacro scope(options, do: context) do
    do_scope(options, context)
  end

  @doc """
  Define a scope with the given path.

  This function is a shortcut for:

      scope path: path do
        ...
      end

  """
  defmacro scope(path, options, do: context) do
    options = quote do
      path = unquote(path)
      case unquote(options) do
        alias when is_atom(alias) -> [path: path, alias: alias]
        options when is_list(options) -> Keyword.put(options, :path, path)
      end
    end
    do_scope(options, context)
  end

  @doc """
  Defines a scope with the given path and alias.

  This function is a shortcut for:

      scope path: path, alias: alias do
        ...
      end

  """
  defmacro scope(path, alias, options, do: context) do
    options = quote do
      unquote(options)
      |> Keyword.put(:path, unquote(path))
      |> Keyword.put(:alias, unquote(alias))
    end
    do_scope(options, context)
  end

  defp do_scope(options, context) do
    quote do
      Scope.push(__MODULE__, unquote(options))
      try do
        unquote(context)
      after
        Scope.pop(__MODULE__)
      end
    end
  end

  @doc """
  Forwards a request at the given path to a plug.

  All paths that matches the forwarded prefix will be sent to
  the forwarded plug. This is useful to share router between
  applications or even break a big router into smaller ones.
  The router pipelines will be invoked prior to forwarding the
  connection.

  Note, however, that we don't advise forwarding to another
  endpoint. The reason is that plugs defined by your app
  and the forwarded endpoint would be invoked twice, which
  may lead to errors.

  ## Examples

      scope "/", MyApp do
        pipe_through [:browser, :admin]

        forward "/admin", SomeLib.AdminDashboard
        forward "/api", ApiRouter
      end

  """
  defmacro forward(path, plug, plug_opts \\ [], router_opts \\ []) do
    router_opts = Keyword.put(router_opts, :as, nil)

    quote unquote: true, bind_quoted: [path: path, plug: plug] do
      path_segments = Route.forward_path_segments(path, plug, @phoenix_forwards)
      @phoenix_forwards Map.put(@phoenix_forwards, plug, path_segments)
      unquote(add_route(:forward, :*, path, plug, plug_opts, router_opts))
    end
  end
end

defmodule Phoenix.Router do
  defmodule NoRouteError do
    @moduledoc """
    Exception raised when no route is found.
    """
    defexception plug_status: 404, message: "no route found", conn: nil, router: nil

    def exception(opts) do
      conn   = Keyword.fetch!(opts, :conn)
      router = Keyword.fetch!(opts, :router)
      path   = "/" <> Enum.join(conn.path_info, "/")

      %NoRouteError{message: "no route found for #{conn.method} #{path} (#{inspect router})",
                    conn: conn, router: router}
    end
  end

  @moduledoc """
  Defines a Phoenix router.

  The router provides a set of macros for generating routes
  that dispatch to specific controllers and actions. Those
  macros are named after HTTP verbs. For example:

      defmodule MyApp.Router do
        use Phoenix.Router

        get "/pages/:page", PageController, :show
      end

  The `get/3` macro above accepts a request of format "/pages/VALUE" and
  dispatches it to the show action in the `PageController`.

  Routes can also match glob-like patterns, routing any path with a common
  base to the same controller. For example:

      get "/dynamic*anything", DynamicController, :show

  Phoenix's router is extremely efficient, as it relies on Elixir
  pattern matching for matching routes and serving requests.

  ### Helpers

  Phoenix automatically generates a module `Helpers` inside your router
  which contains named helpers to help developers generate and keep
  their routes up to date.

  Helpers are automatically generated based on the controller name.
  For example, the route:

      get "/pages/:page", PageController, :show

  will generate the following named helper:

      MyApp.Router.Helpers.page_path(conn_or_endpoint, :show, "hello")
      "/pages/hello"

      MyApp.Router.Helpers.page_path(conn_or_endpoint, :show, "hello", some: "query")
      "/pages/hello?some=query"

      MyApp.Router.Helpers.page_url(conn_or_endpoint, :show, "hello")
      "http://example.com/pages/hello"

      MyApp.Router.Helpers.page_url(conn_or_endpoint, :show, "hello", some: "query")
      "http://example.com/pages/hello?some=query"

  The url generated in the named url helpers is based on the configuration for
  `:url`, `:http` and `:https`.

  The named helper can also be customized with the `:as` option. Given
  the route:

      get "/pages/:page", PageController, :show, as: :special_page

  the named helper will be:

      MyApp.Router.Helpers.special_page_path(conn, :show, "hello")
      "/pages/hello"

  ### Scopes and Resources

  The router also supports scoping of routes:

      scope "/api/v1", as: :api_v1 do
        get "/pages/:id", PageController, :show
      end

  For example, the route above will match on the path `"/api/v1/pages/:id"
  and the named route will be `api_v1_page_path`, as expected from the
  values given to `scope/2` option.

  Phoenix also provides a `resources/4` macro that allows developers
  to generate "RESTful" routes to a given resource:

      defmodule MyApp.Router do
        use Phoenix.Router

        resources "/pages", PageController, only: [:show]
        resources "/users", UserController, except: [:delete]
      end

  Finally, Phoenix ships with a `mix phoenix.routes` task that nicely
  formats all routes in a given router. We can use it to verify all
  routes included in the router above:

      $ mix phoenix.routes
      page_path  GET    /pages/:id       PageController.show/2
      user_path  GET    /users           UserController.index/2
      user_path  GET    /users/:id/edit  UserController.edit/2
      user_path  GET    /users/new       UserController.new/2
      user_path  GET    /users/:id       UserController.show/2
      user_path  POST   /users           UserController.create/2
      user_path  PATCH  /users/:id       UserController.update/2
                 PUT    /users/:id       UserController.update/2

  One can also pass a router explicitly as an argument to the task:

      $ mix phoenix.routes MyApp.Router

  Check `scope/2` and `resources/4` for more information.

  ## Pipelines and plugs

  Once a request arrives at the Phoenix router, it performs
  a series of transformations through pipelines until the
  request is dispatched to a desired end-point.

  Such transformations are defined via plugs, as defined
  in the [Plug](http://github.com/elixir-lang/plug) specification.
  Once a pipeline is defined, it can be piped through per scope.

  For example:

      defmodule MyApp.Router do
        use Phoenix.Router

        pipeline :browser do
          plug :fetch_session
          plug :accepts, ["html"]
        end

        scope "/" do
          pipe_through :browser

          # browser related routes and resources
        end
      end

  `Phoenix.Router` imports functions from both `Plug.Conn` and `Phoenix.Controller`
  to help define plugs. In the example above, `fetch_session/2`
  comes from `Plug.Conn` while `accepts/2` comes from `Phoenix.Controller`.

  Note that router pipelines are only invoked after a route is found.
  No plug is invoked in case no matches were found.

  """

  alias Phoenix.Router.Resource
  alias Phoenix.Router.Scope
  alias Phoenix.Router.Route
  alias Phoenix.Router.Helpers

  @http_methods [:get, :post, :put, :patch, :delete, :options, :connect, :trace, :head]

  @doc false
  defmacro __using__(_) do
    quote do
      unquote(prelude())
      unquote(defs())
      unquote(match_dispatch())
    end
  end

  defp prelude() do
    quote do
      Module.register_attribute __MODULE__, :phoenix_routes, accumulate: true
      @phoenix_forwards %{}

      import Phoenix.Router
      import Plug.Conn
      import Phoenix.Controller

      # Set up initial scope
      @phoenix_pipeline nil
      Phoenix.Router.Scope.init(__MODULE__)
      @before_compile unquote(__MODULE__)
    end
  end

  # Because those macros are executed multiple times,
  # we end-up generating a huge scope that drastically
  # affects compilation. We work around it by defining
  # those functions only once and calling it over and
  # over again.
  defp defs() do
    quote unquote: false do
      var!(add_resources, Phoenix.Router) = fn resource ->
        path = resource.path
        ctrl = resource.controller
        opts = resource.route

        if !resource.singleton do
          param = resource.param

          Enum.each resource.actions, fn
            :index   -> get    path,                             ctrl, :index, opts
            :show    -> get    path <> "/:" <> param,            ctrl, :show, opts
            :new     -> get    path <> "/new",                   ctrl, :new, opts
            :edit    -> get    path <> "/:" <> param <> "/edit", ctrl, :edit, opts
            :create  -> post   path,                             ctrl, :create, opts
            :delete  -> delete path <> "/:" <> param,            ctrl, :delete, opts
            :update  ->
              patch path <> "/:" <> param, ctrl, :update, opts
              put   path <> "/:" <> param, ctrl, :update, Keyword.put(opts, :as, nil)
          end
        else
          Enum.each resource.actions, fn
            :show    -> get    path,            ctrl, :show, opts
            :new     -> get    path <> "/new",  ctrl, :new, opts
            :edit    -> get    path <> "/edit", ctrl, :edit, opts
            :create  -> post   path,            ctrl, :create, opts
            :delete  -> delete path,            ctrl, :delete, opts
            :update  ->
              patch path, ctrl, :update, opts
              put   path, ctrl, :update, Keyword.put(opts, :as, nil)
          end
        end
      end
    end
  end

  defp match_dispatch() do
    quote location: :keep do
      @behaviour Plug

      @doc """
      Callback required by Plug that initializes the router
      for serving web requests.
      """
      def init(opts) do
        opts
      end

      @doc """
      Callback invoked by Plug on every request.
      """
      def call(conn, opts), do: do_call(conn, opts)

      defp match_route(conn, []) do
        match_route(conn, conn.method, Enum.map(conn.path_info, &URI.decode/1), conn.host)
      end

      defp dispatch(conn, []) do
        try do
          conn.private.phoenix_route.(conn)
        catch
          kind, reason ->
            Plug.Conn.WrapperError.reraise(conn, kind, reason)
        end
      end

      defoverridable [init: 1, call: 2]
    end
  end

  @doc false
  defmacro __before_compile__(env) do
    routes = env.module |> Module.get_attribute(:phoenix_routes) |> Enum.reverse
    routes_with_exprs = Enum.map(routes, &{&1, Route.exprs(&1)})

    Helpers.define(env, routes_with_exprs)
    matches = Enum.map(routes_with_exprs, &build_match/1)

    plugs = [{:dispatch, [], true}, {:match_route, [], true}]
    {conn, pipeline} = Plug.Builder.compile(env, plugs, [])

    call =
      quote do
        unquote(conn) =
          update_in unquote(conn).private,
            &(&1 |> Map.put(:phoenix_pipelines, [])
                 |> Map.put(:phoenix_router, __MODULE__)
                 |> Map.put(__MODULE__, {unquote(conn).script_name, @phoenix_forwards}))
        unquote(pipeline)
      end

    # line: -1 is used here to avoid warnings if forwarding to root path
    match_404 =
      quote line: -1 do
        defp match_route(conn, _method, _path_info, _host) do
          raise NoRouteError, conn: conn, router: __MODULE__
        end
      end

    quote do
      defp do_call(unquote(conn), opts) do
        unquote(call)
      end

      @doc false
      def __routes__,  do: unquote(Macro.escape(routes))

      @doc false
      def __helpers__, do: __MODULE__.Helpers

      unquote(matches)
      unquote(match_404)
    end
  end

  defp build_match({_route, exprs}) do
    quote do
      defp match_route(var!(conn), unquote(exprs.verb_match), unquote(exprs.path),
                 unquote(exprs.host)) do
        unquote(exprs.dispatch)
      end
    end
  end

  @doc """
  Generates a route match based on an arbitrary HTTP method

  Useful for defining routes not included in the builtin macros:

  #{Enum.map_join(@http_methods, ", ", &"`#{&1}`")}

  ## Examples

      match(:move, "/events/:id", EventController, :move)

  """
  defmacro match(verb, path, plug, plug_opts, options \\ []) do
    add_route(:match, verb, path, plug, plug_opts, options)
  end

  for verb <- @http_methods do
    @doc """
    Generates a route to handle a #{verb} request to the given path.
    """
    defmacro unquote(verb)(path, plug, plug_opts, options \\ []) do
      verb = unquote(verb)
      quote bind_quoted: binding do
        match(verb, path, plug, plug_opts, options)
      end
    end
  end

  defp add_route(kind, verb, path, plug, plug_opts, options) do
    quote do
      @phoenix_routes Scope.route(__MODULE__, unquote(kind), unquote(verb), unquote(path),
                                  unquote(plug), unquote(plug_opts), unquote(options))
    end
  end

  @doc """
  Defines a plug pipeline.

  Pipelines are defined at the router root and can be used
  from any scope.

  ## Examples

      pipeline :api do
        plug :token_authentication
        plug :dispatch
      end

  A scope may then use this pipeline as:

      scope "/" do
        pipe_through :api
      end

  Every time `pipe_through/1` is called, the new pipelines
  are appended to the ones previously given.
  """
  defmacro pipeline(plug, do: block) do
    block =
      quote do
        plug = unquote(plug)
        @phoenix_pipeline []
        unquote(block)
      end

    compiler =
      quote unquote: false do
        Scope.pipeline(__MODULE__, plug)
        {conn, body} = Plug.Builder.compile(__ENV__, @phoenix_pipeline, [])
        defp unquote(plug)(unquote(conn), _) do
          try do
            unquote(body)
          catch
            kind, reason ->
              Plug.Conn.WrapperError.reraise(unquote(conn), kind, reason)
          end
        end
        @phoenix_pipeline nil
      end

    quote do
      try do
        unquote(block)
        unquote(compiler)
      after
        :ok
      end
    end
  end

  @doc """
  Defines a plug inside a pipeline.

  See `pipeline/2` for more information.
  """
  defmacro plug(plug, opts \\ []) do
    quote do
      if pipeline = @phoenix_pipeline do
        @phoenix_pipeline [{unquote(plug), unquote(opts), true}|pipeline]
      else
        raise "cannot define plug at the router level, plug must be defined inside a pipeline"
      end
    end
  end

  @doc """
  Defines a pipeline to send the connection through.

  See `pipeline/2` for more information.
  """
  defmacro pipe_through(pipes) do
    quote do
      if pipeline = @phoenix_pipeline do
        raise "cannot pipe_through inside a pipeline"
      else
        Scope.pipe_through(__MODULE__, unquote(pipes))
      end
    end
  end

  @doc """
  Defines "RESTful" routes for a resource.

  The given definition:

      resources "/users", UserController

  will include routes to the following actions:

    * `GET /users` => `:index`
    * `GET /users/new` => `:new`
    * `POST /users` => `:create`
    * `GET /users/:id` => `:show`
    * `GET /users/:id/edit` => `:edit`
    * `PATCH /users/:id` => `:update`
    * `PUT /users/:id` => `:update`
    * `DELETE /users/:id` => `:delete`

  ## Options

  This macro accepts a set of options:

    * `:only` - a list of actions to generate routes for, for example: `[:show, :edit]`
    * `:except` - a list of actions to exclude generated routes from, for example: `[:delete]`
    * `:param` - the name of the paramter for this resource, defaults to `"id"`
    * `:name` - the prefix for this resource. This is used for the named helper
      and as the prefix for the parameter in nested resources. The default value
      is automatically derived from the controller name, i.e. `UserController` will
      have name `"user"`
    * `:as` - configures the named helper exclusively
    * `:singleton` - defines routes for a singleton resource that is looked up by
      the client without referencing an ID. Read below for more information

  ## Singleton resources

  When a resource needs to be looked up without referencing an ID, because
  it contains only a single entry in the given context, the `:singleton`
  option can be used to generate a set of routes that are specific to
  such single resource:

    * `GET /user` => `:show`
    * `GET /user/new` => `:new`
    * `POST /user` => `:create`
    * `GET /user/edit` => `:edit`
    * `PATCH /user` => `:update`
    * `PUT /user` => `:update`
    * `DELETE /user` => `:delete`

    Usage example:

      `resources "/account", AccountController, only: [:show], singleton: true`

  """
  defmacro resources(path, controller, opts, do: nested_context) do
    add_resources path, controller, opts, do: nested_context
  end

  @doc """
  See `resources/4`.
  """
  defmacro resources(path, controller, do: nested_context) do
    add_resources path, controller, [], do: nested_context
  end

  @doc """
  See `resources/4`.
  """
  defmacro resources(path, controller, opts) do
    add_resources path, controller, opts, do: nil
  end

  @doc """
  See `resources/4`.
  """
  defmacro resources(path, controller) do
    add_resources path, controller, [], do: nil
  end

  defp add_resources(path, controller, options, do: context) do
    scope =
      if context do
        quote do
          scope resource.member, do: unquote(context)
        end
      end

    quote do
      resource = Resource.build(unquote(path), unquote(controller), unquote(options))
      var!(add_resources, Phoenix.Router).(resource)
      unquote(scope)
    end
  end

  @doc """
  Defines a scope in which routes can be nested.

  ## Examples

      scope "/api/v1", as: :api_v1, alias: API.V1 do
        get "/pages/:id", PageController, :show
      end

  The generated route above will match on the path `"/api/v1/pages/:id"
  and will dispatch to `:show` action in `API.V1.PageController`. A named
  helper `api_v1_page_path` will also be generated.

  ## Options

  The supported options are:

    * `:path` - a string containing the path scope
    * `:as` - a string or atom containing the named helper scope
    * `:alias` - an alias (atom) containing the controller scope
    * `:host` - a string containing the host scope, or prefix host scope,
      ie `"foo.bar.com"`, `"foo."`
    * `:private` - a map of private data to merge into the connection when a route matches
    * `:assigns` - a map of data to merge into the connection when a route matches

  """
  defmacro scope(options, do: context) do
    do_scope(options, context)
  end

  @doc """
  Define a scope with the given path.

  This function is a shortcut for:

      scope path: path do
        ...
      end

  """
  defmacro scope(path, options, do: context) do
    options = quote do
      path = unquote(path)
      case unquote(options) do
        alias when is_atom(alias) -> [path: path, alias: alias]
        options when is_list(options) -> Keyword.put(options, :path, path)
      end
    end
    do_scope(options, context)
  end

  @doc """
  Defines a scope with the given path and alias.

  This function is a shortcut for:

      scope path: path, alias: alias do
        ...
      end

  """
  defmacro scope(path, alias, options, do: context) do
    options = quote do
      unquote(options)
      |> Keyword.put(:path, unquote(path))
      |> Keyword.put(:alias, unquote(alias))
    end
    do_scope(options, context)
  end

  defp do_scope(options, context) do
    quote do
      Scope.push(__MODULE__, unquote(options))
      try do
        unquote(context)
      after
        Scope.pop(__MODULE__)
      end
    end
  end

  @doc """
  Forwards a request at the given path to a plug.

  All paths that matches the forwarded prefix will be sent to
  the forwarded plug. This is useful to share router between
  applications or even break a big router into smaller ones.
  The router pipelines will be invoked prior to forwarding the
  connection.

  Note, however, that we don't advise forwarding to another
  endpoint. The reason is that plugs defined by your app
  and the forwarded endpoint would be invoked twice, which
  may lead to errors.

  ## Examples

      scope "/", MyApp do
        pipe_through [:browser, :admin]

        forward "/admin", SomeLib.AdminDashboard
        forward "/api", ApiRouter
      end

  """
  defmacro forward(path, plug, plug_opts \\ [], router_opts \\ []) do
    router_opts = Keyword.put(router_opts, :as, nil)

    quote unquote: true, bind_quoted: [path: path, plug: plug] do
      path_segments = Route.forward_path_segments(path, plug, @phoenix_forwards)
      @phoenix_forwards Map.put(@phoenix_forwards, plug, path_segments)
      unquote(add_route(:forward, :*, path, plug, plug_opts, router_opts))
    end
  end
end


Add stage column to retros

Add stage column to retros

defmodule RemoteRetro.Repo.Migrations.AddStageColumnToRetros do
  use Ecto.Migration

  def change do
    alter table(:retros) do
      add :stage, :string, default: "idea-generation"
    end
  end
end

error: pathspec 'priv/repo/migrations/20170425010129_add_stage_column_to_retros.exs' did not match any file(s) known to git


Added a solution for a currecy conversion question.  There is definitely a better solution, but this is the direction I went in the interview.

#!/usr/bin/env elixir

# PROBLEM:
# Given the following data, write a routine to convert from one currency to another.
#
# {:jpy, :usd} => 0.0092,
# {:jpy, :euro} => 0.0078,
# {:usd, :cad} => 1.26,
# {:usd, :aud} => 1.3,
# {:usd, :pond} => 0.73,
# {:pond, :sfr} => 1.29,
# {:euro, :sfr} => 1.11,
#
# Note that the program should be able to convert from any of the listed currencies to
# any of the other listed currencies.  For example, JPY -> USD -> CAD.
#
# After getting to the point where my solution fails to convert from POND to EURO
# through SFR, I would have to say that this is a good interview question.  In retrospect,
# I would just fill out an NxN lookup table on initialization.  Alternatively, I could
# cull the list of supported currencies to prevent an infinite recursive search.
#
# This attempt kind of works, and it will need to be good enough.

defmodule Script do
  # this should probably be precomputed only once
  def currencies(rates) do
    rates
    |> Enum.reduce([], fn {{from, to}, _}, acc -> acc ++ [from, to] end)
    |> Enum.uniq
  end

  # not what I wanted, but I made it work
  def conversion_flatmap(conversions, acc, key) do
    if values = conversions[key] do
      Enum.flat_map(values, fn v -> conversion_flatmap(conversions, acc ++ [key], v) end)
    else
      acc ++ [key]
    end
  end

  # this is what I used to make the flatmap work
  def conversion_list(_conversions, from, from), do: [[from, from]]
  def conversion_list(conversions, from, to) do
    {result, _} =
      conversions
      |> conversion_flatmap([], from)
      # specifically, this reduce
      |> Enum.reduce({[],nil},
        fn
          ^from, {l,_} -> {l,[from]}
          _, a={_,nil} -> a
          ^to, {l,pl} -> {l++[pl++[to]], nil}
          next, {l,pl} -> {l,pl++[next]}
          _, a -> a
        end
      )
    result
    # duplicates can happen
    |> Enum.uniq
  end

  def build_rate_chain_list(rates, from, to) do
    # this should be precomputed and stored, but it will be left as is
    conversions =
      Enum.reduce(rates, %{},
        fn {{from, to}, _}, a ->
          {_, a} = Map.get_and_update(a, from, fn c -> {c, (c || []) ++ [to]} end)
          a
        end
      )
    conversion_list(conversions, from, to)
  end

  # this is basically a custom reduce
  def resolve_rate_chain(_rates, [_h | []], a), do: a
  def resolve_rate_chain(_rates, [from, from], a), do: a
  def resolve_rate_chain(rates, [h | t], a) do
    resolve_rate_chain(rates, t, a * rates[{h, List.first(t)}])
  end

  # handles inverse and reverse, but needs a new strategy to handle EURO -> SFR -> POND
  def convert(rates, from, to) do
    result = build_rate_chain_list(rates, from, to)
    |> Enum.map(fn r -> {r, resolve_rate_chain(rates, r, 1)} end)
    if 0 < length(result) do
      result
    else
      build_rate_chain_list(rates, to, from)
      |> Enum.map(fn r -> {r |> Enum.reverse, 1/resolve_rate_chain(rates, r, 1)} end)
    end
  end

  # it is used a couple of times
  def print_rate_header(rate_list) do
    rate_list
    |> Enum.join(" -> ")
    |> IO.write
    IO.write(" = ")
  end

  # for visual feedback
  def print_rate(rates, from, to) do
    rate_list = convert(rates, from, to)
    if 0 < length(rate_list) do
      Enum.each(rate_list, fn {r, v} -> print_rate_header(r); IO.puts("#{v}") end)
    else
      print_rate_header([from, to])
      IO.puts("ERROR")
    end
  end

  # may as well put all of these in one place
  def test(rates) do
    IO.puts("--- Forward ---")
    main(["jpy:usd", "jpy:euro", "usd:cad", "usd:aud", "usd:pond", "pond:sfr", "euro:sfr"])

    IO.puts("\n--- Backward ---")
    main(["usd:jpy", "euro:jpy", "cad:usd", "aud:usd", "pond:usd", "sfr:pond", "sfr:euro"])

    IO.puts("\n--- Chain Conversion ---")
    main(["jpy:cad", "jpy:sfr", "cad:jpy", "sfr:jpy"])

    IO.puts("\n--- Self Conversion ---")
    main(["aud:aud", "cad:cad", "euro:euro", "jpy:jpy", "pond:pond", "sfr:sfr", "usd:usd"])

    IO.puts("\n--- Bad Conversion ---")
    print_rate(rates, :usd, :btc)
    print_rate(rates, :btc, :usd)
  end

  # extra polish
  def usage(rates) do
    IO.puts("Usage:")
    IO.puts("  #{:escript.script_name()} FROM:TO [FROM:TO ...]")
    IO.puts("  #{:escript.script_name()} help")
    IO.puts("  #{:escript.script_name()} test")
    IO.puts("")
    IO.write("Currencies: ")
    rates
    |> currencies
    |> Enum.sort
    |> Enum.map(&Atom.to_string/1)
    |> Enum.map(&String.upcase/1)
    |> Enum.join(", ")
    |> IO.puts
    IO.puts("")
    IO.puts("Example:")
    IO.puts("  #{:escript.script_name()} SFR:USD JPY:SFR POND:EURO USD:JPY")
  end

  # now takes command line arguments
  def main(args) do
    rates = %{
      {:jpy, :usd} => 0.0092,
      {:jpy, :euro} => 0.0078,
      {:usd, :cad} => 1.26,
      {:usd, :aud} => 1.30,
      {:usd, :pond} => 0.73,
      {:pond, :sfr} => 1.29,
      {:euro, :sfr} => 1.11,
    }
    currencies = rates |> currencies
    args = args |> Enum.map(&String.downcase/1)
    cond do
      Enum.member?(args, "test") -> test(rates)
      Enum.member?(args, "help") -> usage(rates)
      0 == length(args) -> usage(rates)
      true ->
        job_list = args
          |> Enum.map(fn s ->
            result = String.split(s, ":") |> Enum.map(&String.to_atom/1)
            if [true] == result |> Enum.map(&Enum.member?(currencies, &1)) |> Enum.uniq do
              result
            else
              :error
            end
          end
        )
        unless Enum.member?(job_list, :error) do
          job_list |> Enum.each(fn [from, to] -> print_rate(rates, from, to) end)
        else
          usage(rates)
        end
    end
  end
end

# everythign starts here
Script.main(System.argv)

error: pathspec 'currency_conversion.exs' did not match any file(s) known to git


Add UpsideDownLeds.Master

Add UpsideDownLeds.Master

defmodule UpsideDownLeds.Master do
  use GenServer

  ## client API

  @doc """
  Starts the server.
  """
  def start_link(options \\ %{}) do
    GenServer.start_link(__MODULE__, options, [])
  end

  ## server callbacks

  def init do
    {:ok, lights} = UpsideDownLeds.BlinkingLights.start_link
    {:ok, twitter} = UpsideDownLeds.TwitterListener.start_link(fn text -> UpsideDownLeds.BlinkingLights.puts(lights, text); text end)
    {:ok, lights: lights, twitter: twitter}
  end
end

error: pathspec 'lib/upside_down_leds/master.ex' did not match any file(s) known to git


Player

Player

defmodule Battleship.Player do
  defstruct [
    id: nil,
    name: nil
  ]
end

error: pathspec 'web/models/player.ex' did not match any file(s) known to git


Readded deleted file

Readded deleted file

# Configure at http://www.twitchalerts.com/oauth/apps/register
TWITCH_INFO = {
    'client_id': '',
    'client_secret': '',
    'redirect_uri': 'http://localhost:8000/twitchalerts/authorize'
}

error: pathspec 'alerts/twitchalerts/app_info.py.ex' did not match any file(s) known to git


Fixes host name in prod config.

Fixes host name in prod config.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/futhr/ribbon.git/'


Add Connect specs.

Add Connect specs.

defmodule PixieConnectSpec do
  use ESpec

  describe "handle" do
    let :client_id do
      %{id: c_id} = Pixie.Backend.create_client
      c_id
    end

    let :event do
      m = Pixie.Message.Connect.init message
      r = Pixie.Response.init m
      %Pixie.Event{message: m, response: r}
    end

    let :handled, do: Pixie.Connect.handle event

    let :response do
      %{response: response} = handled
      response
    end

    let :client do
      %{client: client} = handled
      client
    end

    finally do: Pixie.Backend.destroy_client client_id

    describe "When passed a message with no client_id" do
      let :message, do: %{channel: "/meta/connect", connection_type: "long-polling"}

      it "sets a parameter missing response" do
        expect(response.error).to start_with("402:clientId:")
      end
    end

    describe "When passed a message with no channel" do
      let :message, do: %{client_id: client_id, connection_type: "long-polling"}

      it "sets a parameter missing response" do
        expect(response.error).to start_with("402:channel:")
      end
    end

    describe "When passed a message with no connection_type" do
      let :message, do: %{client_id: client_id, channel: "/meta/connect"}

      it "sets a parameter missing response" do
        expect(response.error).to start_with("402:connectionType:")
      end
    end

    describe "When passed a message with an invalid client_id" do
      let :message, do: %{client_id: "abcd1234"}

      it "sets a client unknown response" do
        expect(response.error).to start_with("401:abcd1234")
      end
    end
  end
end

error: pathspec 'spec/connect_spec.exs' did not match any file(s) known to git


Fix is_public field assignment in camera creation


Add authenticate_admin tests

Add authenticate_admin tests

defmodule ElixirJobs.Accounts.Services.AuthenticateAdminTest do
  use ElixirJobs.DataCase

  alias ElixirJobs.Accounts.Schemas.Admin
  alias ElixirJobs.Accounts.Services.AuthenticateAdmin

  describe "AuthenticateAdmin.call/2" do
    test "authenticate admin users" do
      admin = insert(:admin)

      {result, resource} = AuthenticateAdmin.call(admin.email, admin.password)

      assert result == :ok
      assert %Admin{} = resource
      assert resource.id == admin.id
    end

    test "returns error on wrong password" do
      admin = insert(:admin)

      {result, resource} = AuthenticateAdmin.call(admin.email, "wadus")

      assert result == :error
      assert resource == :wrong_credentials
    end

    test "returns error on wrong email" do
      {result, resource} = AuthenticateAdmin.call("invent@email.com", "wadus")

      assert result == :error
      assert resource == :wrong_credentials
    end
  end
end

error: pathspec 'test/elixir_jobs/accounts/services/authenticate_admin_test.exs' did not match any file(s) known to git


ops medication request dates search fixed (#3919)


function call

function call

defmodule Mod do
  def func1 do
    IO.puts "in func1"
  end

  def func2 do
    func1
    IO.puts "In func2"
  end
end

Mod.func1
Mod.func2

error: pathspec 'elixir/96.exs' did not match any file(s) known to git


exercise

exercise

defmodule Recursive do
  def sum(0), do: 0
  def sum(n), do: n + sum(n-1)
end

Recursive.sum(1)
|> IO.puts

Recursive.sum(3)
|> IO.puts

error: pathspec 'elixir/53.exs' did not match any file(s) known to git


Add test

Add test

defmodule Xema.BoolLogicTest do
  use ExUnit.Case

  doctest Xema.Any

  import Xema

  describe "keyword not:" do
    setup do
      %{schema: xema(:any, not: :integer)}
    end

    test "type", %{schema: schema} do
      assert schema.type.as == :any
    end

    test "validate/2 with a string", %{schema: schema} do
      assert validate(schema, "foo") == :ok
    end
  end
end

error: pathspec 'test/xema/bool_logic_test.exs' did not match any file(s) known to git


Formatting

Formatting

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/evercam/evercam-media.git/'


Adding multiple attack

Adding multiple attack


Added game context insert, sorting and searching problem.

#!/usr/bin/env elixir

# PROBLEM:
# Tactical and strategy games are often about positioning army units on a map.
# Typically maps can be represented by cartesian grids of arbitrarily large sizes.
#
# Implement a data structure that allows:
# - Adding an army unit at a coordinate (x, y);
# - Checking for units at a coordinate (x, y);
# - Scanning the map for units using an **iterator**
#   should start from low y values to high y values.
#
# Expect that scanning is used more often that checking/adding/removing.

defmodule Script do
  # maintain hashmap for individual unit search and a presorted list for scanning the map
  # time complexity is O(N) to maintain the sorted list
  def add_unit({hashmap, sorted_list}, position={x, y}, type) do
    {
      Map.put(hashmap, position, type),
      sorted_list
      # overwrite existing unit at position
      |> Enum.filter(fn {^x, ^y, _} -> false; _ -> true end)
      |> Kernel.++([{x, y, type}])
      # sort by Y, then by X
      |> Enum.sort(
        fn
          {ax, y, _}, {bx, y, _} -> ax <= bx;
          {_, ay, _}, {_, by, _} -> ay <= by
        end
      )
    }
  end

  # get individual unit from hashmap
  # time complexity is O(1) for a good hashmap
  def get_unit({hashmap, _sorted_list}, position={x, y}) do
    hashmap
    |> Map.get(position)
    |> case do
      nil -> {x, y, :none}
      t -> {x, y, t}
    end
  end

  # return presorted list for scanning the map
  # time complexity is O(1)
  def get_sorted_units({_hashmap, sorted_list}) do
    sorted_list
  end

  # test data
  def load_units do
    units = [
      {11, 45, :small_b},
      {11, 44, :small_c},
      {9, 7, :medium},
      {10, 44, :small_a},
      {0, -1, :large},
    ]
    Enum.reduce(units, {%{}, []}, fn {x, y, t}, acc -> add_unit(acc, {x, y}, t) end)
  end

  # test output
  def print_unit_at_position(map_state, search_position) do
    {x, y, type} = get_unit(map_state, search_position)
    IO.puts("(#{x}, #{y}) => #{type}")
  end

  # test output
  def print_all_units(map_state={_hashmap, sorted_list}) do
    sorted_list
    |> Enum.each(
      fn {x, y, _} ->
        print_unit_at_position(map_state, {x, y})
      end
    )
  end

  def test(map_state) do
    IO.puts("Units:")
    [
      {0, 0},
      {11, 44},
      {-1000, -1000},
    ]
    |> Enum.each(&print_unit_at_position(map_state, &1))
    IO.puts("")
    IO.puts("Map Data:")
    print_all_units(map_state)
  end

  # extra polish
  def usage(map_state) do
    IO.puts("Usage:")
    IO.puts("  #{:escript.script_name()} x,y [x,y ...]")
    IO.puts("  #{:escript.script_name()} help")
    IO.puts("  #{:escript.script_name()} test")
    IO.puts("")
    IO.puts("Units: ")
    print_all_units(map_state)
    IO.puts("")
    IO.puts("Examples:")
    IO.puts("  #{:escript.script_name()} 9,7")
    IO.puts("  #{:escript.script_name()} 0,-1 0,0 0,1")
    IO.puts("  #{:escript.script_name()} 10,44 10,45 11,44 11,45")
  end

  # now takes command line arguments
  def main(args) do
    map_state = load_units()
    map_state = add_unit(map_state, {0, 0}, :player)
    args = args |> Enum.map(&String.downcase/1)
    cond do
      Enum.member?(args, "test") -> test(map_state)
      Enum.member?(args, "help") -> usage(map_state)
      0 == length(args) -> usage(map_state)
      true ->
        search_positions = args
          |> Enum.map(fn s ->
            result = String.split(s, ",")
            |> Enum.map(
              fn v ->
                v
                |> Integer.parse
                |> case do
                  {v, _} -> v
                  _ -> :error
                end
              end
            )
            if 2 != length(result) || Enum.member?(result, :error) do
              :error
            else
              List.to_tuple(result)
            end
          end
        )
        unless Enum.member?(search_positions, :error) do
          search_positions
          |> Enum.each(&print_unit_at_position(map_state, &1))
        else
          usage(map_state)
        end
    end
  end
end

# everything starts here
Script.main(System.argv)

error: pathspec 'map_units.exs' did not match any file(s) known to git


Create a project and a memberhip on UserController.create

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/babie/goal-server.git/'


event

event

fatal: unable to access 'https://github.com/MaraniMatias/elixir-HelloWorld.git/': The requested URL returned error: 403


Start deletion on new filer. (#1033)

Start deletion on new filer. (#1033)


Fixed broken camera

Fixed broken camera

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/evercam/evercam-server.git/'


Calculate primes using list comprehensions

defmodule Prime do
  # Return a list of primary numbers from 2 to n.
  def primes_up_to(n) when n < 2, do: :error
  def primes_up_to(n) do
    for x <- span(2, n), prime?(x), do: x
  end

  # Returns true if the given number is prime, otherwise false.
  def prime?(n) when n <= 0, do: :error
  def prime?(n) when n == 1, do: false
  def prime?(n) when n == 2, do: true
  def prime?(n) do
    # Use Trial division to calculate primes
    # https://en.wikipedia.org/wiki/Trial_division
    span(2, round(:math.sqrt(n)))
    |> Enum.all?(&rem(n, &1) != 0)
  end

  # Return a list of values between from and to.
  def span(from, to) when from >= to, do: [from]
  def span(from, to), do: [from | span(from + 1, to)]
end

error: pathspec 'recursion/prime.exs' did not match any file(s) known to git


Add lint config

Add lint config

use Mix.Config

# Do not include metadata nor timestamps in development logs
config :logger, :console, format: "[$level] $message\n"

error: pathspec 'config/lint.exs' did not match any file(s) known to git


don't check origins in production

don't check origins in production

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/simplabs/ember-workshop-server.git/'


Minor change to test config

Minor change to test config


Whitespace

Whitespace


Refactor snapshot thumbnail function

Refactor snapshot thumbnail function


Actually, simplify implementation

Actually, simplify implementation

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/edenlabllc/ehealth.api.git/'


Work around Gandalf problem, item 3

Work around Gandalf problem, item 3


Do not local install into subdirectories

error: RPC failed; HTTP 403 curl 22 The requested URL returned error: 403
fatal: the remote end hung up unexpectedly


Use at least 20 db connections in prod

Use at least 20 db connections in prod

fatal: unable to access 'https://github.com/kholbekj/phoenix.git/': The requested URL returned error: 403


Create module for file related functions

defmodule DrinkMe.Files do
  def tmpfile(data, path) do
    {:ok, file} = path
                  |> extract_filename
                  |> tmp_path
                  |> File.open [:write]
    :ok = IO.binwrite file, data
    File.close(file)
    {:ok, path}
  end

  def extract_filename(path) do
    ext = path |> Path.extname
    path
    |> Path.basename(ext)
    |> match_name
  end

  defp tmp_path(path) do
    Path.join System.tmp_dir, (path <> "--" <> random_str)
  end

  defp match_name(path) do
    [_| tail] = Regex.run(~r/(.*)(-[-|shrunk])?/, path)
    tail |> List.first
  end

  defp random_str() do
    Enum.map_join 1..5, fn(_) ->
      "abcdefghijklmnopqrstuvwxyz0123456789" |> String.at :random.uniform(36) - 1
    end
  end
end

error: pathspec 'lib/drink_me/files.ex' did not match any file(s) known to git


Add Serum.Project.LoaderTest

Add Serum.Project.LoaderTest

fatal: unable to access 'https://github.com/Dalgona/Serum.git/': The requested URL returned error: 403


Added migration script to change columns data type (#605)


Correct Broadcast parameter

Correct Broadcast parameter


add pipeOperator

add pipeOperator

# Pipe Operator
# The pipe operator |> passes the result of an expression as the first parameter of another expression.

# foo(bar(baz(nueva_function(otra_function()))))                  # bad :(
# otra_function() |> nueva_function() |> baz() |> bar() |> foo()  # Good :)

"Elixir language" |> String.split                                 # ["Elixir", "language"]
"Elixir language" |> String.split |> Enum.map( &String.upcase/1 ) # ["ELIXIR", "LANGUAGE"]
"elixir" |> String.ends_with?("ixir") |> IO.puts                  # true
# "elixir" |> String.ends_with? "ixir"                              # true

error: pathspec 'basic/pipeOperator.exs' did not match any file(s) known to git


Refactor storage cleanup to reduce duplication


Add Serum.Build.FileLoader.Common

Add Serum.Build.FileLoader.Common

defmodule Serum.Build.FileLoader.Common do
  @moduledoc false

  _moduledocp = "Provides common functions shared by other file loader modules"

  alias Serum.Result

  @doc false
  @spec get_subdir(binary(), binary()) :: binary()
  def get_subdir(src, subdir) do
    (src == "." && subdir) || Path.join(src, subdir)
  end

  @doc false
  @spec read_files([binary()]) :: Result.t([Serum.File.t()])
  def read_files(paths) do
    paths
    |> Stream.map(&%Serum.File{src: &1})
    |> Enum.map(&Serum.File.read/1)
    |> Result.aggregate_values(:file_loader)
  end
end

error: pathspec 'lib/serum/build/file_loader/common.ex' did not match any file(s) known to git


Quick sort in Elixir

Quick sort in Elixir

fatal: unable to access 'https://github.com/sylviot/algoritmos.git/': The requested URL returned error: 403


add snake_start_length to bs_repo_game table

defmodule BsRepo.Migrations.AddSnakeStartLengthToBsRepoGame do
  use Ecto.Migration

  def change do
    alter table(:bs_repo_game) do
      add :snake_start_length, :any
    end
  end
end

error: pathspec 'priv/bs_repo/migrations/20180118023100_add_snake_start_length_to_bs_repo_game.exs' did not match any file(s) known to git


Remove mix task for password hashing

Remove mix task for password hashing

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/evercam/evercam-media.git/'


Add parser of leapseconds file. This will be removed again, because we will parse and use leap-seconds.list instead. The reason is that the leap-seconds.list file has a TAI offset column which is useful. Also it is more generally available.

defmodule Tzdata.LeapSecParser2 do
  import Tzdata.Util
  @moduledoc false
  # Parsing of the leap second file `leapseconds`

  @file_name "leapseconds"
  def read_file(dir_prepend \\ "source_data", file_name \\ @file_name) do
    File.stream!("#{dir_prepend}/#{file_name}")
    |> process_file
  end

  defp process_file(file_stream) do
    file_stream
    |> filter_comment_lines
    |> filter_empty_lines
    |> Stream.map(&(strip_comment(&1))) # Strip comments at line end. Like this comment.
    |> Stream.map(&(process_line(&1)))
  end

  @line_regex ~r/Leap[\s]+(?<year>[^\s]+)[\s]+(?<month>[^\s]+)[\s]+(?<day>[^\s]+)[\s]+(?<hour>[\d]+):(?<min>[\d]+):(?<sec>[\d]+)[\s]+(?<correction>[^\s])[\s]+(?<rolling_or_stationary>[^\s])/
  defp process_line(line) do
    map = Regex.named_captures(@line_regex, line)
    month = month_number_for_month_name(map["month"])
    %{ datetime: {{to_int(map["year"]),month, to_int(map["day"]) },
                  {to_int(map["hour"]), to_int(map["min"]), to_int(map["sec"])}},
       is_utc: map["rolling_or_stationary"]=="S",
       is_additive: map["correction"] == "+"
    }
  end
end

error: pathspec 'lib/tzdata/leap_sec_parser2.ex' did not match any file(s) known to git


seed some categories in a way they can be rerun

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/jacklin10/rumbl.git/'


Add incidents table.

Add incidents table.

defmodule SlackCoder.Repo.Migrations.AddFlamesIncidentsTable do
  use Ecto.Migration

  def change do
    create table(:error_incidents) do
      add :error_id, references(:errors)
      add :message, :text
      add :timestamp, :datetime

      timestamps
    end
  end
end

error: pathspec 'priv/repo/migrations/20160623042109_add_flames_incidents_table.exs' did not match any file(s) known to git


Separate updating camera status and saving snapshots


began adding clicks cache

began adding clicks cache

defmodule OptionCalc.Utilities.GenDataCache do

    @timeout 1000

    def start_link() do
        # get initiall values
        {:ok, pid} = Agent.start_link(fn-> %{ total_bucket_island: 0, total_other: 0 } end, name: __MODULE__)
        :timer.send_interval(@timeout, :commit)
    end

    def get_value_async(process, key, query) do
        cached = Agent.get(process, fn x -> x[key] end)
    end

    def get_value(process, query) do
        cached = Agent.get(process, fn x -> x end)
    end

    def set_value(process, value) do
        cached_value = %{ value: value, cached_on: DateTime.utc_now, status: :ready }
        Agent.update(process, fn state -> Map.put(state, key, cached_value) end)
    end

    def is_valid(cached_data) do
        cached_on = cached_data.cached_on |> DateTime.to_unix
        cached_on + @timeout > DateTime.utc_now |> DateTime.to_unix
    end

end

error: pathspec 'lib/bucketisland/Services/ClickTotalsCache.ex' did not match any file(s) known to git


Exception raising example

Exception raising example

defmodule Ok do
  def ok!({ :ok, data }), do: data
  def ok!({ _, error }), do: raise "Error: #{error}"
end

error: pathspec '12_control_flow/ok.exs' did not match any file(s) known to git