Bump version number

Bump version number

defmodule Vutuv.Mixfile do
  use Mix.Project

  def project do
    [app: :vutuv,
     version: "1.1.2",
     elixir: "~> 1.0",
     elixirc_paths: elixirc_paths(Mix.env),
     compilers: [:phoenix, :gettext] ++ Mix.compilers,
     build_embedded: Mix.env == :prod,
     start_permanent: Mix.env == :prod,
     aliases: aliases,
     deps: deps]
  end

  # Configuration for the OTP application.
  #
  # Type `mix help compile.app` for more information.
  def application do
    [mod: {Vutuv, []},
     applications: [:phoenix,
                    :phoenix_pubsub,
                    :phoenix_html,
                    :cowboy,
                    :logger,
                    :gettext,
                    :phoenix_ecto,
                    :ex_machina,
                    :phoenix_html_simplified_helpers,
                    :bamboo,
                    :bamboo_smtp,
                    :mariaex,
                    :httpoison,
                    :slugger,
                    :timex_ecto,
                    :word_smith,
                    :arc,
                    :arc_ecto]]
  end

  # Specifies which paths to compile per environment.
  defp elixirc_paths(:test), do: ["lib", "web", "test/support"]
  defp elixirc_paths(_),     do: ["lib", "web"]

  # Specifies your project dependencies.
  #
  # Type `mix help deps` for examples and options.
  defp deps do
    [{:ecto, "~> 2.0.0", override: true},
     {:bamboo, "~> 0.6"},
     {:bamboo_smtp, "~> 1.1.0"},
     {:phoenix, "~> 1.2.0"},
     {:phoenix_ecto, "~> 3.0.0-rc"},
     {:phoenix_html, "~> 2.8"},
     {:phoenix_live_reload, "~> 1.0", only: :dev},
     {:gettext, "~> 0.12.1"},
     {:cowboy, "~> 1.0"},
     {:arc, "~> 0.5.3"},
     {:arc_ecto, "~> 0.4.2"},
     {:ex_machina, "~> 0.6.1"},
     {:phoenix_html_simplified_helpers, "~> 0.6.0"},
     {:mariaex, ">= 0.0.0"},
     {:word_smith, "~> 0.1.0"},
     {:slugger, "~> 0.1.0"},
     {:httpoison, "~> 0.9.0"},
     {:distillery, "~> 0.10"}]
  end

  # Aliases are shortcut or tasks specific to the current project.
  # For example, to create, migrate and run the seeds file at once:
  #
  #     $ mix ecto.setup
  #
  # See the documentation for `Mix` for more info on aliases.
  defp aliases do
    ["ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"],
     "ecto.reset": ["ecto.drop", "ecto.setup"],
     "test": ["ecto.create --quiet", "ecto.migrate", "test"]]
  end
end

defmodule Vutuv.Mixfile do
  use Mix.Project

  def project do
    [app: :vutuv,
     version: "1.1.1",
     elixir: "~> 1.0",
     elixirc_paths: elixirc_paths(Mix.env),
     compilers: [:phoenix, :gettext] ++ Mix.compilers,
     build_embedded: Mix.env == :prod,
     start_permanent: Mix.env == :prod,
     aliases: aliases,
     deps: deps]
  end

  # Configuration for the OTP application.
  #
  # Type `mix help compile.app` for more information.
  def application do
    [mod: {Vutuv, []},
     applications: [:phoenix,
                    :phoenix_pubsub,
                    :phoenix_html,
                    :cowboy,
                    :logger,
                    :gettext,
                    :phoenix_ecto,
                    :ex_machina,
                    :phoenix_html_simplified_helpers,
                    :bamboo,
                    :bamboo_smtp,
                    :mariaex,
                    :httpoison,
                    :slugger,
                    :timex_ecto,
                    :word_smith,
                    :arc,
                    :arc_ecto]]
  end

  # Specifies which paths to compile per environment.
  defp elixirc_paths(:test), do: ["lib", "web", "test/support"]
  defp elixirc_paths(_),     do: ["lib", "web"]

  # Specifies your project dependencies.
  #
  # Type `mix help deps` for examples and options.
  defp deps do
    [{:ecto, "~> 2.0.0", override: true},
     {:bamboo, "~> 0.6"},
     {:bamboo_smtp, "~> 1.1.0"},
     {:phoenix, "~> 1.2.0"},
     {:phoenix_ecto, "~> 3.0.0-rc"},
     {:phoenix_html, "~> 2.8"},
     {:phoenix_live_reload, "~> 1.0", only: :dev},
     {:gettext, "~> 0.12.1"},
     {:cowboy, "~> 1.0"},
     {:arc, "~> 0.5.3"},
     {:arc_ecto, "~> 0.4.2"},
     {:ex_machina, "~> 0.6.1"},
     {:phoenix_html_simplified_helpers, "~> 0.6.0"},
     {:mariaex, ">= 0.0.0"},
     {:word_smith, "~> 0.1.0"},
     {:slugger, "~> 0.1.0"},
     {:httpoison, "~> 0.9.0"},
     {:distillery, "~> 0.10"}]
  end

  # Aliases are shortcut or tasks specific to the current project.
  # For example, to create, migrate and run the seeds file at once:
  #
  #     $ mix ecto.setup
  #
  # See the documentation for `Mix` for more info on aliases.
  defp aliases do
    ["ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"],
     "ecto.reset": ["ecto.drop", "ecto.setup"],
     "test": ["ecto.create --quiet", "ecto.migrate", "test"]]
  end
end


cow boy

cow boy

defmodule Eeb.Mixfile do
  use Mix.Project

  def project do
    [app: :eeb,
     version: "0.0.1",
     aliases: aliases,
     elixir: "~> 1.1",
     source_url: "https://github.com/aborn/eeb",
     homepage_url: "https://github.com/aborn/eeb",
     build_embedded: Mix.env == :prod,
     start_permanent: Mix.env == :prod,
     deps: deps]
  end

  # Configuration for the OTP application
  #
  # Type "mix help compile.app" for more information
  def application do
    [env: [default: :value],
     applications: [:logger,:tzdata,:cowboy]
    ]
  end

  # Dependencies can be Hex packages:
  #
  #   {:mydep, "~> 0.3.0"}
  #
  # Or git/path repositories:
  #
  #   {:mydep, git: "https://github.com/elixir-lang/mydep.git", tag: "0.1.0"}
  #
  # Type "mix help deps" for more examples and options
  defp deps do
    [{:earmark, "~> 0.1.19", only: :dev},
     {:ex_doc, "~> 0.11.1", only: :dev},
     {:timex, "~> 1.0.0"},
     { :cowboy, "~> 1.0" },
     { :plug, "~> 0.14" },
     {:tzdata, "== 0.1.8", override: true}]  ## https://github.com/bitwalker/timex/issues/86
  end

  defp aliases do
    [compile: ["deps.check", &unload_hex/1, "compile"],
     run: [&unload_hex/1, "run"],
     install: ["archive.build -o eeb.ez", "archive.install eeb.ez --force"],
     uninstall: ["archive.uninstall eeb.ez"]]
  end

  defp unload_hex(_) do
    paths = Path.join(Mix.Local.archives_path, "eeb*.ez") |> Path.wildcard

    Enum.each(paths, fn archive ->
      ebin = Mix.Archive.ebin(archive)
      Code.delete_path(ebin)

      {:ok, files} = :erl_prim_loader.list_dir(to_char_list(ebin))

      Enum.each(files, fn file ->
        file = List.to_string(file)
        size = byte_size(file) - byte_size(".beam")

        case file do
          <<name :: binary-size(size), ".beam">> ->
            module = String.to_atom(name)
            :code.delete(module)
            :code.purge(module)
          _ ->
            :ok
        end
      end)
    end)
  end

end

defmodule Eeb.Mixfile do
  use Mix.Project

  def project do
    [app: :eeb,
     version: "0.0.1",
     aliases: aliases,
     elixir: "~> 1.1",
     source_url: "https://github.com/aborn/eeb",
     homepage_url: "https://github.com/aborn/eeb",
     build_embedded: Mix.env == :prod,
     start_permanent: Mix.env == :prod,
     deps: deps]
  end

  # Configuration for the OTP application
  #
  # Type "mix help compile.app" for more information
  def application do
    [env: [default: :value],
     applications: [:logger,:tzdata]
    ]
  end

  # Dependencies can be Hex packages:
  #
  #   {:mydep, "~> 0.3.0"}
  #
  # Or git/path repositories:
  #
  #   {:mydep, git: "https://github.com/elixir-lang/mydep.git", tag: "0.1.0"}
  #
  # Type "mix help deps" for more examples and options
  defp deps do
    [{:earmark, "~> 0.1.19", only: :dev},
     {:ex_doc, "~> 0.11.1", only: :dev},
     {:timex, "~> 1.0.0"},
     { :cowboy, "~> 1.0" },
     { :plug, "~> 0.14" },
     {:tzdata, "== 0.1.8", override: true}]  ## https://github.com/bitwalker/timex/issues/86
  end

  defp aliases do
    [compile: ["deps.check", &unload_hex/1, "compile"],
     run: [&unload_hex/1, "run"],
     install: ["archive.build -o eeb.ez", "archive.install eeb.ez --force"],
     uninstall: ["archive.uninstall eeb.ez"]]
  end

  defp unload_hex(_) do
    paths = Path.join(Mix.Local.archives_path, "eeb*.ez") |> Path.wildcard

    Enum.each(paths, fn archive ->
      ebin = Mix.Archive.ebin(archive)
      Code.delete_path(ebin)

      {:ok, files} = :erl_prim_loader.list_dir(to_char_list(ebin))

      Enum.each(files, fn file ->
        file = List.to_string(file)
        size = byte_size(file) - byte_size(".beam")

        case file do
          <<name :: binary-size(size), ".beam">> ->
            module = String.to_atom(name)
            :code.delete(module)
            :code.purge(module)
          _ ->
            :ok
        end
      end)
    end)
  end

end


Also remove roadmap from docs [ci skip]

Also remove roadmap from docs [ci skip]

unless Code.ensure_loaded?(Appsignal.Agent) do
  {_, _} = Code.eval_file("agent.ex")
end

defmodule Mix.Tasks.Compile.Appsignal do
  use Mix.Task

  def run(_args) do
    {_, _} = Code.eval_file("mix_helpers.exs")

    case Mix.Appsignal.Helper.verify_system_architecture() do
      {:ok, arch} ->
        :ok = Mix.Appsignal.Helper.ensure_downloaded(arch)
        :ok = Mix.Appsignal.Helper.compile
      {:error, {:unsupported, arch}} ->
        Mix.Shell.IO.error("Unsupported target platform #{arch}, AppSignal integration disabled!\nPlease check http://docs.appsignal.com/support/operating-systems.html")
        :ok
    end
  end
end

defmodule Appsignal.Mixfile do
  use Mix.Project
  @agent_version Appsignal.Agent.version

  def project do
    [app: :appsignal,
     version: "1.0.4",
     name: "AppSignal",
     description: description(),
     package: package(),
     source_url: "https://github.com/appsignal/appsignal-elixir",
     homepage_url: "https://appsignal.com",
     test_paths: test_paths(Mix.env),
     elixir: "~> 1.0",
     compilers: compilers(Mix.env),
     elixirc_paths: elixirc_paths(Mix.env),
     deps: deps(),
     docs: [logo: "logo.png"],
     agent_version: @agent_version
    ]
  end

  defp description do
    "Collects error and performance data from your Elixir applications and sends it to AppSignal"
  end

  defp package do
    %{files: ["lib", "c_src/*.[ch]", "mix.exs", "mix_helpers.exs",
              "*.md", "LICENSE", "Makefile", "agent.ex"],
      maintainers: ["Arjan Scherpenisse", "Jeff Kreeftmeijer", "Tom de Bruijn"],
      licenses: ["MIT"],
      links: %{"GitHub" => "https://github.com/appsignal/appsignal-elixir"}}
  end

  def application do
    [mod: {Appsignal, []},
     applications: [:logger, :decorator, :httpoison]]
  end

  defp compilers(:test_phoenix), do: [:phoenix] ++ compilers(:prod)
  defp compilers(_), do: [:appsignal] ++ Mix.compilers

  defp test_paths(:test_phoenix), do: ["test/appsignal", "test/mix", "test/phoenix"]
  defp test_paths(_), do: ["test/appsignal", "test/mix"]

  defp elixirc_paths(env) do
    case test?(env) do
      true -> ["lib", "test/support"]
      false -> ["lib"]
    end
  end

  defp test?(:test), do: true
  defp test?(:test_phoenix), do: true
  defp test?(:test_no_nif), do: true
  defp test?(_), do: false

  defp deps do
    [
      {:httpoison, "~> 0.11"},
      {:decorator, "~> 1.0"},
      {:phoenix, ">= 1.2.0", optional: true, only: [:prod, :test_phoenix]},
      {:mock, "~> 0.2.1", only: [:test, :test_phoenix, :test_no_nif]},
      {:bypass, "~> 0.5", only: [:test, :test_phoenix, :test_no_nif]},
      {:ex_doc, "~> 0.12", only: :dev, runtime: false}
    ]
  end
end

unless Code.ensure_loaded?(Appsignal.Agent) do
  {_, _} = Code.eval_file("agent.ex")
end

defmodule Mix.Tasks.Compile.Appsignal do
  use Mix.Task

  def run(_args) do
    {_, _} = Code.eval_file("mix_helpers.exs")

    case Mix.Appsignal.Helper.verify_system_architecture() do
      {:ok, arch} ->
        :ok = Mix.Appsignal.Helper.ensure_downloaded(arch)
        :ok = Mix.Appsignal.Helper.compile
      {:error, {:unsupported, arch}} ->
        Mix.Shell.IO.error("Unsupported target platform #{arch}, AppSignal integration disabled!\nPlease check http://docs.appsignal.com/support/operating-systems.html")
        :ok
    end
  end
end

defmodule Appsignal.Mixfile do
  use Mix.Project
  @agent_version Appsignal.Agent.version

  def project do
    [app: :appsignal,
     version: "1.0.4",
     name: "AppSignal",
     description: description(),
     package: package(),
     source_url: "https://github.com/appsignal/appsignal-elixir",
     homepage_url: "https://appsignal.com",
     test_paths: test_paths(Mix.env),
     elixir: "~> 1.0",
     compilers: compilers(Mix.env),
     elixirc_paths: elixirc_paths(Mix.env),
     deps: deps(),
     docs: [logo: "logo.png", extras: ["Roadmap.md"]],
     agent_version: @agent_version
    ]
  end

  defp description do
    "Collects error and performance data from your Elixir applications and sends it to AppSignal"
  end

  defp package do
    %{files: ["lib", "c_src/*.[ch]", "mix.exs", "mix_helpers.exs",
              "*.md", "LICENSE", "Makefile", "agent.ex"],
      maintainers: ["Arjan Scherpenisse", "Jeff Kreeftmeijer", "Tom de Bruijn"],
      licenses: ["MIT"],
      links: %{"GitHub" => "https://github.com/appsignal/appsignal-elixir"}}
  end

  def application do
    [mod: {Appsignal, []},
     applications: [:logger, :decorator, :httpoison]]
  end

  defp compilers(:test_phoenix), do: [:phoenix] ++ compilers(:prod)
  defp compilers(_), do: [:appsignal] ++ Mix.compilers

  defp test_paths(:test_phoenix), do: ["test/appsignal", "test/mix", "test/phoenix"]
  defp test_paths(_), do: ["test/appsignal", "test/mix"]

  defp elixirc_paths(env) do
    case test?(env) do
      true -> ["lib", "test/support"]
      false -> ["lib"]
    end
  end

  defp test?(:test), do: true
  defp test?(:test_phoenix), do: true
  defp test?(:test_no_nif), do: true
  defp test?(_), do: false

  defp deps do
    [
      {:httpoison, "~> 0.11"},
      {:decorator, "~> 1.0"},
      {:phoenix, ">= 1.2.0", optional: true, only: [:prod, :test_phoenix]},
      {:mock, "~> 0.2.1", only: [:test, :test_phoenix, :test_no_nif]},
      {:bypass, "~> 0.5", only: [:test, :test_phoenix, :test_no_nif]},
      {:ex_doc, "~> 0.12", only: :dev, runtime: false}
    ]
  end
end


Script execution docs

Script execution docs

defmodule Hound.JsonDriver.ScriptExecution do
  import Hound.JsonDriver.Utils

  @doc """
  Execute javascript synchoronously.

  * The first argument is the script to execute.
  * The second argument is a list of arguments that is passed.
    These arguments are accessible in the script via `arguments`.

          execute_script("return(arguments[0] + arguments[1]);", [1, 2])

          execute_script("doSomething(); return(arguments[0] + arguments[1]);")
  """
  @spec execute_script(String.t, List.t) :: any
  def execute_script(script_function, function_args // []) do
    session_id = Hound.get_current_session_id
    make_req(:post,
      "session/#{session_id}/execute",
      [script: script_function, args: function_args]
    )
  end

  @doc """
  Execute javascript asynchoronously.

  * The first argument is the script to execute.
  * The second argument is a list of arguments that is passed.
    These arguments are accessible in the script via `arguments`.

  Webdriver passes a callback function as the last argument to the script.
  When your script has completed execution, it has to call the last argument,
  which is a callback function, to indicate that the execute is complete.

      # Once we perform whatever we want,
      # we call the callback function with the arguments that must be returned.
      execute_script_async("doSomething(); arguments[arguments.length-1]('hello')", [])

      # We have no arguments to pass, so we'll skip the second argument.
      execute_script_async("console.log('hello'); doSomething(); arguments[arguments.length-1]()")

  Unless you call the callback function, the function is not assumed to be completed.
  It will error out.
  """
  @spec execute_script_async(String.t, List.t) :: any
  def execute_script_async(script_function, function_args // []) do
    session_id = Hound.get_current_session_id
    make_req(:post,
      "session/#{session_id}/execute_async",
      [script: script_function, args: function_args]
    )
  end
end

defmodule Hound.JsonDriver.ScriptExecution do
  import Hound.JsonDriver.Utils

  @doc """
  Execute javascript synchoronously.

  * The first argument is the script to execute.
  * The second argument is a list of arguments that is passed.
    These arguments are accessible in the script via `arguments`.
  """
  @spec execute_script(String.t, List.t) :: any
  def execute_script(script_function, function_args // []) do
    session_id = Hound.get_current_session_id
    make_req(:post,
      "session/#{session_id}/execute",
      [script: script_function, args: function_args]
    )
  end

  @doc """
  Execute javascript asynchoronously.

  * The first argument is the script to execute.
  * The second argument is a list of arguments that is passed.
    These arguments are accessible in the script via `arguments`.

    Webdriver passes a callback function as the last argument to the script.
    When your script has completed execution, it has to call the last argument, to indicate that the execute is complete.
  """
  @spec execute_script_async(String.t, List.t) :: any
  def execute_script_async(script_function, function_args // []) do
    session_id = Hound.get_current_session_id
    make_req(:post,
      "session/#{session_id}/execute_async",
      [script: script_function, args: function_args]
    )
  end
end


Add more tests for comparisons

Add more tests for comparisons

defmodule ChoicestWeb.ComparisonControllerTest do
  use ChoicestWeb.ConnCase

  alias Choicest.Contestants
  alias Choicest.Contestants.Image

  @create_attrs %{content_type: "some content_type", description: "some description", file_size: 42, filename: "some filename", url: "some url"}
  @missing_image 99999999

  def fixture(:image) do
    {:ok, image} = Contestants.create_image(@create_attrs)
    image
  end

  def fixture(:comparison) do
    %Image{id: winner_id} = fixture(:image)
    %Image{id: loser_id} = fixture(:image)

    {:ok, comparison} = Contestants.create_comparison(winner_id, loser_id)

    comparison
  end

  defp create_image(_) do
    image = fixture(:image)
    {:ok, image: image}
  end

  defp create_winner_loser(_) do
    %Image{id: winner_id} = fixture(:image)
    %Image{id: loser_id} = fixture(:image)

    {:ok, winner_id: winner_id, loser_id: loser_id}
  end

  defp create_comparison(_) do
    comparison = fixture(:comparison)
    {:ok, comparison: comparison}
  end

  setup %{conn: conn} do
    {:ok, conn: put_req_header(conn, "accept", "application/json")}
  end

  describe "create comparison" do
    setup [:create_winner_loser]

    test "creates comparison between images", %{conn: conn, winner_id: winner_id, loser_id: loser_id} do
      conn = post conn, "/api/comparisons/", %{winner_id: winner_id, loser_id: loser_id}

      assert %{"winner" => winner} = json_response(conn, 201)["data"]
      assert %{"loser" => loser} = json_response(conn, 201)["data"]

      assert winner["id"] == winner_id
      assert loser["id"] == loser_id
    end

    test "returns error if one or both of the images are missing", %{conn: conn, winner_id: winner_id, loser_id: loser_id} do
      assert_error_sent 404, fn ->
        post conn, "/api/comparisons/", %{winner_id: winner_id, loser_id: @missing_image}
      end

      assert_error_sent 404, fn ->
        post conn, "/api/comparisons/", %{winner_id: @missing_image, loser_id: loser_id}
      end

      assert_error_sent 404, fn ->
        post conn, "/api/comparisons/", %{winner_id: @missing_image, loser_id: @missing_image}
      end
    end
  end

  describe "get comparison by id" do
    setup [:create_comparison]

    test "gets existing comparison by id", %{conn: conn, comparison: comparison} do
      conn = get conn, "/api/comparisons/#{comparison.id}"

      assert %{"id" => id} = json_response(conn, 200)["data"]
      assert %{"winner" => winner} = json_response(conn, 200)["data"]
      assert %{"loser" => loser} = json_response(conn, 200)["data"]

      assert winner["id"] == comparison.winner_id
      assert loser["id"] == comparison.loser_id

      assert id == comparison.id
    end

    test "returns error for missing image", %{conn: conn} do
      assert_error_sent 404, fn ->
        get conn, "/api/comparisons/99999999"
      end
    end
  end

  describe "comparison results" do
    setup [:create_image]

    test "lists empty comparisons correctly", %{conn: conn, image: image} do
      conn = get conn, "/api/comparisons/results/#{image.id}"
      assert json_response(conn, 200)["won_against"] == []
      assert json_response(conn, 200)["lost_against"] == []
    end
  end
end

defmodule ChoicestWeb.ComparisonControllerTest do
  use ChoicestWeb.ConnCase

  alias Choicest.Contestants
  alias Choicest.Contestants.Image

  @create_attrs %{content_type: "some content_type", description: "some description", file_size: 42, filename: "some filename", url: "some url"}

  def fixture(:image) do
    {:ok, image} = Contestants.create_image(@create_attrs)
    image
  end

  def fixture(:comparison) do
    %Image{id: winner_id} = fixture(:image)
    %Image{id: loser_id} = fixture(:image)

    {:ok, comparison} = Contestants.create_comparison(winner_id, loser_id)

    comparison
  end

  defp create_image(_) do
    image = fixture(:image)
    {:ok, image: image}
  end

  defp create_winner_loser(_) do
    %Image{id: winner_id} = fixture(:image)
    %Image{id: loser_id} = fixture(:image)

    {:ok, winner_id: winner_id, loser_id: loser_id}
  end

  defp create_comparison(_) do
    comparison = fixture(:comparison)
    {:ok, comparison: comparison}
  end

  setup %{conn: conn} do
    {:ok, conn: put_req_header(conn, "accept", "application/json")}
  end

  describe "create comparison" do
    setup [:create_winner_loser]

    test "creates comparison between images", %{conn: conn, winner_id: winner_id, loser_id: loser_id} do
      conn = post conn, "/api/comparisons/", %{winner_id: winner_id, loser_id: loser_id}

      assert %{"winner" => winner} = json_response(conn, 201)["data"]
      assert %{"loser" => loser} = json_response(conn, 201)["data"]

      assert winner["id"] == winner_id
      assert loser["id"] == loser_id
    end
  end

  describe "get comparison by id" do
    setup [:create_comparison]

    test "gets existing comparison by id", %{conn: conn, comparison: comparison} do
      conn = get conn, "/api/comparisons/#{comparison.id}"

      assert %{"id" => id} = json_response(conn, 200)["data"]
      assert %{"winner" => winner} = json_response(conn, 200)["data"]
      assert %{"loser" => loser} = json_response(conn, 200)["data"]

      assert winner["id"] == comparison.winner_id
      assert loser["id"] == comparison.loser_id

      assert id == comparison.id
    end
  end

  describe "comparison results" do
    setup [:create_image]

    test "lists empty comparisons correctly", %{conn: conn, image: image} do
      conn = get conn, "/api/comparisons/results/#{image.id}"
      assert json_response(conn, 200)["won_against"] == []
      assert json_response(conn, 200)["lost_against"] == []
    end
  end
end


Fix migration for adding done to task lists

defmodule CodeCorps.Repo.Migrations.AddDoneToTaskList do
  use Ecto.Migration

  import Ecto.Query

  alias CodeCorps.Repo

  def up do
    alter table(:task_lists) do
      add :done, :boolean, default: false
    end

    flush()

    from(tl in "task_lists", where: [name: "Done"], update: [set: [done: true]])
    |> Repo.update_all([])

    task_list_query =
      from(tl in "task_lists", where: [done: true], select: [:id])

    task_list_query |> Repo.all() |> Enum.each(fn task ->
      # tests do not have any data, so we need to account for potential nil
      case task do
        %{id: done_list_id} ->
          task_update_query = from t in "tasks",
            where: [status: "closed"],
            update: [set: [task_list_id: ^done_list_id]]
          task_update_query |> Repo.update_all([])
        nil -> nil
      end
    end)
  end

  def down do
    alter table(:task_lists) do
      remove :done
    end
  end
end

defmodule CodeCorps.Repo.Migrations.AddDoneToTaskList do
  use Ecto.Migration

  import Ecto.Query

  alias CodeCorps.Repo

  def up do
    alter table(:task_lists) do
      add :done, :boolean, default: false
    end

    flush()

    from(tl in "task_lists", where: [name: "Done"], update: [set: [done: true]])
    |> Repo.update_all([])

    task_list_query =
      from(tl in "task_lists", where: [done: true], select: [:id])

    # tests do not have any data, so we need to account for potential nil
    case task_list_query |> Repo.one do
      %{id: done_list_id} ->
        task_update_query = from t in "tasks",
          where: [status: "closed"],
          update: [set: [task_list_id: ^done_list_id]]
        task_update_query |> Repo.update_all([])
      nil -> nil
    end
  end

  def down do
    alter table(:task_lists) do
      remove :done
    end
  end
end


(9.1%) Test case: Error  when re-attaching UART

Mox.defmock(FarmbotFirmware.UartTestAdapter, for: FarmbotFirmware.UartAdapter)

defmodule FarmbotFirmware.UARTTransportTest do
  use ExUnit.Case
  import Mox
  setup [:verify_on_exit!]
  doctest FarmbotFirmware.UARTTransport
  alias FarmbotFirmware.{UartTestAdapter, UARTTransport}

  test "UARTTransport.init/1" do
    expect(UartTestAdapter, :start_link, fn ->
      {:ok, :FAKE_UART}
    end)

    init_args = [
      device: :FAKE_DEVICE,
      handle_gcode: :FAKE_GCODE_HANDLER,
      reset: :FAKE_RESETER
    ]

    {:ok, state, 0} = UARTTransport.init(init_args)
    assert state.device == Keyword.fetch!(init_args, :device)
    assert state.handle_gcode == Keyword.fetch!(init_args, :handle_gcode)
    assert state.reset == Keyword.fetch!(init_args, :reset)
  end

  test "UARTTransport.terminate/2" do
    expect(UartTestAdapter, :stop, fn uart ->
      assert uart == :whatever
    end)

    state = %{uart: :whatever}
    UARTTransport.terminate(nil, state)
  end

  test "UARTTransport resets UART on timeout" do
    state = %{uart: :FAKE_UART, device: :FAKE_DEVICE, open: false}

    fake_opts = [fake_opts: true]

    expect(UartTestAdapter, :generate_opts, fn ->
      fake_opts
    end)

    expect(UartTestAdapter, :open, fn uart, dev, opts ->
      assert uart == state.uart
      assert dev == state.device
      assert fake_opts == opts
      :ok
    end)

    {:noreply, state2} = UARTTransport.handle_info(:timeout, state)
    # Expect the `open` state to toggle back to "true" from "false":
    refute state.open == state2.open
  end

  test "UARTTransport handles unexpected UART errors" do
    state = %{uart: :FAKE_UART, device: :FAKE_DEVICE, open: false}

    fake_opts = [fake_opts: true]

    expect(UartTestAdapter, :generate_opts, fn ->
      fake_opts
    end)

    expect(UartTestAdapter, :open, fn _, _, _ ->
      {:error, "Simulated UART failure. This is OK"}
    end)

    {:noreply, state2, retry_timeout} = UARTTransport.handle_info(:timeout, state)
    assert retry_timeout == 5000
    assert state.open == state2.open
  end

  test "UARTTransport.reset/2" do
    empty_state = %{reset: nil}
    ok_state = %{reset: %{reset: :fake_reset}}
    assert :ok == UARTTransport.reset(empty_state)
    assert :fake_reset == UARTTransport.reset(ok_state)
  end

  test "UARTTransport.open/2" do
    me = self()

    expect(UartTestAdapter, :open, fn pid, path, opts ->
      assert pid == me
      assert path == "/dev/null"
      assert opts == [a: :b]
    end)

    UARTTransport.open(me, "/dev/null", a: :b)
  end
end

Mox.defmock(FarmbotFirmware.UartTestAdapter, for: FarmbotFirmware.UartAdapter)

defmodule FarmbotFirmware.UARTTransportTest do
  use ExUnit.Case
  import Mox
  setup [:verify_on_exit!]
  doctest FarmbotFirmware.UARTTransport

  test "FarmbotFirmware.UARTTransport.init/1" do
    expect(FarmbotFirmware.UartTestAdapter, :start_link, fn ->
      {:ok, :FAKE_UART}
    end)

    init_args = [
      device: :FAKE_DEVICE,
      handle_gcode: :FAKE_GCODE_HANDLER,
      reset: :FAKE_RESETER
    ]

    {:ok, state, 0} = FarmbotFirmware.UARTTransport.init(init_args)
    assert state.device == Keyword.fetch!(init_args, :device)
    assert state.handle_gcode == Keyword.fetch!(init_args, :handle_gcode)
    assert state.reset == Keyword.fetch!(init_args, :reset)
  end

  test "FarmbotFirmware.UARTTransport.terminate/2" do
    expect(FarmbotFirmware.UartTestAdapter, :stop, fn uart ->
      assert uart == :whatever
    end)

    state = %{uart: :whatever}
    FarmbotFirmware.UARTTransport.terminate(nil, state)
  end

  test "FarmbotFirmware.UARTTransport resets UART on timeout" do
    state = %{uart: :FAKE_UART, device: :FAKE_DEVICE, open: false}

    fake_opts = [fake_opts: true]

    expect(FarmbotFirmware.UartTestAdapter, :generate_opts, fn ->
      fake_opts
    end)

    expect(FarmbotFirmware.UartTestAdapter, :open, fn uart, dev, opts ->
      assert uart == state.uart
      assert dev == state.device
      assert fake_opts == opts
      :ok
    end)

    {:noreply, state2} = FarmbotFirmware.UARTTransport.handle_info(:timeout, state)
    # Expect the `open` state to toggle back to "true" from "false":
    refute state.open == state2.open
  end

  test "FarmbotFirmware.UARTTransport.reset/2" do
    empty_state = %{reset: nil}
    ok_state = %{reset: %{reset: :fake_reset}}
    assert :ok == FarmbotFirmware.UARTTransport.reset(empty_state)
    assert :fake_reset == FarmbotFirmware.UARTTransport.reset(ok_state)
  end

  test "FarmbotFirmware.UARTTransport.open/2" do
    me = self()

    expect(FarmbotFirmware.UartTestAdapter, :open, fn pid, path, opts ->
      assert pid == me
      assert path == "/dev/null"
      assert opts == [a: :b]
    end)

    FarmbotFirmware.UARTTransport.open(me, "/dev/null", a: :b)
  end
end


Adapts PageControllerTest to reflect new page content

defmodule Listen.PageControllerTest do
  use Listen.Web.ConnCase

  test "GET /", %{conn: conn} do
    conn = get conn, "/"
    assert html_response(conn, 200) =~ "Listen"
  end
end

defmodule Listen.PageControllerTest do
  use Listen.Web.ConnCase

  test "GET /", %{conn: conn} do
    conn = get conn, "/"
    assert html_response(conn, 200) =~ "Welcome to Phoenix!"
  end
end


three times

three times

defmodule Dot.DotController do
  use Dot.Web, :controller
  require Logger
  def mytime(conn, %{"request" => %{"intent" => %{"name" => "BusStatus", "slots" => %{"Date" => %{"name" => "Date", "value" => busDate}}}}} = params) do

    busStatus = Bus.get(busDate)
    Logger.info(busStatus)
    json conn,
      %{
        "version" => "1.0",
        "sessionAttributes" => %{},
        "response" => %{
          "outputSpeech" => %{
            "type" => "PlainText",
            "text" => "The bus status for " <> busDate <> " is " <> busStatus,
           },
           "shouldEndSession" => true
         }
       }
  end

  def mytime(conn, %{"request" => %{"intent" => %{"name" => "PheasantStop"}}}) do
    [h|t] = Pheasant.timeStop
    json conn,
      %{
        "version" => "1.0",
        "sessionAttributes" => %{},
        "response" => %{
          "outputSpeech" => %{
            "type" => "PlainText",
            "text" => "The next bus arrives at " <> h,
           },
           "shouldEndSession" => true
         }
       }
  end

  def mytime(conn, params) do
    [first|t] = Pheasant.timeStop
    [second|third] = t
    json conn,
      %{
        "version" => "1.0",
        "sessionAttributes" => %{},
        "response" => %{
          "outputSpeech" => %{
            "type" => "PlainText",
            "text" => "The next three buses arrive at " <> first <> " " <> second <> " and " <> third,
           },
           "shouldEndSession" => true
         }
       }
  end
end

defmodule Dot.DotController do
  use Dot.Web, :controller
  require Logger
  def mytime(conn, %{"request" => %{"intent" => %{"name" => "BusStatus", "slots" => %{"Date" => %{"name" => "Date", "value" => busDate}}}}} = params) do

    busStatus = Bus.get(busDate)
    Logger.info(busStatus)
    json conn,
      %{
        "version" => "1.0",
        "sessionAttributes" => %{},
        "response" => %{
          "outputSpeech" => %{
            "type" => "PlainText",
            "text" => "The bus status for " <> busDate <> " is " <> busStatus,
           },
           "shouldEndSession" => true
         }
       }
  end

  def mytime(conn, params) do
    [h|t] = Pheasant.timeStop
    json conn,
      %{
        "version" => "1.0",
        "sessionAttributes" => %{},
        "response" => %{
          "outputSpeech" => %{
            "type" => "PlainText",
            "text" => "The next bus arrives at " <> h,
           },
           "shouldEndSession" => true
         }
       }
  end
end


quiet down tty detector

quiet down tty detector

defmodule FarmbotOS.FirmwareTTYDetector do
  use GenServer
  require Logger
  alias Circuits.UART

  @expected_names Application.get_env(:farmbot, __MODULE__)[:expected_names]
  @expected_names ||
    Mix.raise("""
    Please configure `expected_names` for TTYDetector.

        config :farmbot, Farmbot.TTYDetector,
          expected_names: ["ttyS0", "ttyNotReal"]
    """)

  @error_retry_ms 5_000

  def tty(server \\ __MODULE__) do
    GenServer.call(server, :tty)
  end

  def tty!(server \\ __MODULE__) do
    tty(server) || raise "No TTY detected"
  end

  def start_link(args, opts \\ [name: __MODULE__]) do
    GenServer.start_link(__MODULE__, args, opts)
  end

  def init([]) do
    {:ok, nil, 0}
  end

  def handle_call(:tty, _, detected_tty) do
    {:reply, detected_tty, detected_tty}
  end

  def handle_info(:timeout, state) do
    enumerated = UART.enumerate() |> Map.to_list()
    {:noreply, state, {:continue, enumerated}}
  end

  def handle_continue([{name, _} | rest], state) do
    if farmbot_tty?(name) do
      {:noreply, name}
    else
      # Logger.warn("#{name} is not an expected Farmbot Firmware TTY")
      {:noreply, state, {:continue, rest}}
    end
  end

  def handle_continue([], state) do
    Process.send_after(self(), :timeout, @error_retry_ms)
    {:noreply, state}
  end

  defp farmbot_tty?(file_path) do
    file_path in @expected_names
  end
end

defmodule FarmbotOS.FirmwareTTYDetector do
  use GenServer
  require Logger
  alias Circuits.UART

  @expected_names Application.get_env(:farmbot, __MODULE__)[:expected_names]
  @expected_names ||
    Mix.raise("""
    Please configure `expected_names` for TTYDetector.

        config :farmbot, Farmbot.TTYDetector,
          expected_names: ["ttyS0", "ttyNotReal"]
    """)

  @error_retry_ms 5_000

  def tty(server \\ __MODULE__) do
    GenServer.call(server, :tty)
  end

  def tty!(server \\ __MODULE__) do
    tty(server) || raise "No TTY detected"
  end

  def start_link(args, opts \\ [name: __MODULE__]) do
    GenServer.start_link(__MODULE__, args, opts)
  end

  def init([]) do
    {:ok, nil, 0}
  end

  def handle_call(:tty, _, detected_tty) do
    {:reply, detected_tty, detected_tty}
  end

  def handle_info(:timeout, state) do
    enumerated = UART.enumerate() |> Map.to_list()
    {:noreply, state, {:continue, enumerated}}
  end

  def handle_continue([{name, _} | rest], state) do
    if farmbot_tty?(name) do
      {:noreply, name}
    else
      Logger.warn("#{name} is not an expected Farmbot Firmware TTY")
      {:noreply, state, {:continue, rest}}
    end
  end

  def handle_continue([], state) do
    Process.send_after(self(), :timeout, @error_retry_ms)
    {:noreply, state}
  end

  defp farmbot_tty?(file_path) do
    file_path in @expected_names
  end
end


Fix migration

Fix migration

defmodule Betterdev.Repo.Migrations.AddBotChannelToUser do
  use Ecto.Migration

  def change do
    alter table(:accounts_users) do
      add :channel, :string
      add :channel_user_id, :string
    end
  end
end

defmodule Betterdev.Repo.Migrations.AddBotChannelToUser do
  use Ecto.Migration

  def change do
    alter table(:accounts_users) do
      add :channel, :string
      add :channel_user_id, :string

      create index(:community_link_tags, [:link_id, :tag_id], unique: true)
    end
  end
end


Add failing urls to SharedUrls for posting

defmodule ElixirStatus.Publisher.SharedUrls do
  def for_posting(posting) do
    # TODO: follow redirects
    collect_and_expand_urls(posting.text)
  end

  def collect_and_expand_urls(text) do
    text = Earmark.to_html(text)

    ~r/href=\"([^\"]+?)\"/
    |> Regex.scan(text)
    |> Enum.flat_map(fn([_, url]) ->
        expand_url(url)
      end)
  end

  def expand_url(nil), do: nil
  def expand_url(url, acc \\ []) do
    case HTTPoison.get(url) do
      {:ok, %HTTPoison.Response{status_code: 200}} ->
        acc ++ [url]
      {:ok, %HTTPoison.Response{status_code: 301, headers: headers}} ->
        headers
        |> Enum.find_value(&find_location_header/1)
        |> expand_url(acc ++ [url])
      {:ok, %HTTPoison.Response{status_code: 302, headers: headers}} ->
        headers
        |> Enum.find_value(&find_location_header/1)
        |> expand_url(acc ++ [url])
      {:ok, %HTTPoison.Response{status_code: _status_code}} ->
        acc ++ [url]
      {:error, %HTTPoison.Error{reason: _reason}} ->
        acc ++ [url]
    end
  end

  defp find_location_header({"Location", location}), do: location
  defp find_location_header({"location", location}), do: location
  defp find_location_header(_), do: nil

end

defmodule ElixirStatus.Publisher.SharedUrls do
  def for_posting(posting) do
    # TODO: follow redirects
    collect_and_expand_urls(posting.text)
  end

  def collect_and_expand_urls(text) do
    text = Earmark.to_html(text)

    ~r/href=\"([^\"]+?)\"/
    |> Regex.scan(text)
    |> Enum.flat_map(fn([_, url]) ->
        expand_url(url)
      end)
  end

  def expand_url(nil), do: nil
  def expand_url(url, acc \\ []) do
    case HTTPoison.get(url) do
      {:ok, %HTTPoison.Response{status_code: 200}} ->
        acc ++ [url]
      {:ok, %HTTPoison.Response{status_code: 301, headers: headers}} ->
        headers
        |> Enum.find_value(&find_location_header/1)
        |> expand_url(acc ++ [url])
      {:ok, %HTTPoison.Response{status_code: 302, headers: headers}} ->
        headers
        |> Enum.find_value(&find_location_header/1)
        |> expand_url(acc ++ [url])
      {:ok, %HTTPoison.Response{status_code: status_code}} ->
        nil
      {:error, %HTTPoison.Error{reason: reason}} ->
        nil
    end
  end

  defp find_location_header({"Location", location}), do: location
  defp find_location_header({"location", location}), do: location
  defp find_location_header(_), do: nil

end


add hamming test

add hamming test

if !System.get_env("EXERCISM_TEST_EXAMPLES") do
  Code.load_file("hamming.exs")
end

ExUnit.start
ExUnit.configure exclude: :pending, trace: true

defmodule DNATest do
  use ExUnit.Case

  # @tag :pending
  test "no difference between empty strands" do
    assert DNA.hamming_distance('', '') == 0
  end

  @tag :pending
  test "no difference between identical strands" do
    assert DNA.hamming_distance('GGACTGA', 'GGACTGA') == 0
  end

  @tag :pending
  test "small hamming distance in middle somewhere" do
    assert DNA.hamming_distance('GGACG', 'GGTCG') == 1
  end

  @tag :pending
  test "distance with same nucleotides in different locations" do
    assert DNA.hamming_distance('TAG', 'GAT') == 2
  end

  @tag :pending
  test "larger distance" do
    assert DNA.hamming_distance('ACCAGGG', 'ACTATGG') == 2
  end

  @tag :pending
  test "hamming distance is undefined for strands of different lengths" do
    assert DNA.hamming_distance('AAAC', 'TAGGGGAGGCTAGCGGTAGGAC') == nil
    assert DNA.hamming_distance('GACTACGGACAGGACACC', 'GACATCGC') == nil
  end
end

if !System.get_env("EXERCISM_TEST_EXAMPLES") do
  Code.load_file("hamming.exs")
end

ExUnit.start
ExUnit.configure exclude: :pending, trace: true

defmodule DNATest do
  use ExUnit.Case

  # @tag :pending
  test "no difference between empty strands" do
    assert DNA.hamming_distance('', '') == 0
  end

  @tag :pending
  test "no difference between identical strands" do
    assert DNA.hamming_distance('GGACTGA', 'GGACTGA') == 0
  end

  @tag :pending
  test "small hamming distance in middle somewhere" do
    assert DNA.hamming_distance('GGACG', 'GGTCG') == 1
  end

  @tag :pending
  test "larger distance" do
    assert DNA.hamming_distance('ACCAGGG', 'ACTATGG') == 2
  end

  @tag :pending
  test "hamming distance is undefined for strands of different lengths" do
    assert DNA.hamming_distance('AAAC', 'TAGGGGAGGCTAGCGGTAGGAC') == nil
    assert DNA.hamming_distance('GACTACGGACAGGACACC', 'GACATCGC') == nil
  end
end


fix query

fix query

defmodule Neoscan.BalanceHistories do
  @moduledoc false

  import Ecto.Query, warn: false
  alias Neoscan.Repo
  alias Neoscan.BalanceHistories.History
  alias Neoscan.Transactions
  alias Neoscan.Transactions.Transaction
  alias Neoscan.ChainAssets

  @doc """
  Returns an `%Ecto.Changeset{}` for tracking address history changes.

  ## Examples

      iex> change_history(history)
      %Ecto.Changeset{source: %History{}}

  """
  def change_history(%History{} = history, address, attrs) do
    History.changeset(history, address, attrs)
  end

  #add a transaction history into an address
  def add_tx_id(attrs, txid, index, time) do
    new_tx = %{
      :txid => txid,
      :balance => attrs.balance,
      :block_height => index,
      :time => time
    }
    %{attrs | tx_ids: new_tx}
  end

  @doc """
  Count total history points for an address.

  ## Examples

      iex> count_histories_for_Address(address_hash)
      50

  """
  def count_hist_for_address(address_hash) do
    query = from h in History,
                 where: h.address_hash == ^address_hash
    Repo.aggregate(query, :count, :id)
  end

  def paginate_history_transactions(address_hash, pag) do
    his_query = from h in History,
                  where: h.address_hash == ^address_hash,
                  order_by: [
                    desc: h.time
                  ],
                  select: %{
                    txid: h.txid
                  },
                  limit: 15

    histories = Repo.paginate(his_query, page: pag, page_size: 15)
                |> Enum.map(fn %{:txid => txid} -> txid end)

    transaction_query = from e in Transaction,
                             order_by: [
                               desc: e.block_height
                             ],
                             where: e.txid in ^histories,
                             select: %{
                               :id => e.id,
                               :type => e.type,
                               :time => e.time,
                               :txid => e.txid,
                               :block_height => e.block_height,
                               :block_hash => e.block_hash,
                               :vin => e.vin,
                               :claims => e.claims,
                               :sys_fee => e.sys_fee,
                               :net_fee => e.net_fee,
                               :size => e.size,
                               :asset => e.asset,
                             }

    transactions = Repo.all(transaction_query)
    vouts = Enum.map(transactions, fn tx -> tx.id end)
            |> Transactions.get_transactions_vouts

    transactions
    |> Enum.map(
         fn tx ->
           Map.put(
             tx,
             :vouts,
             Enum.filter(
               vouts,
               fn vout ->
                 vout.transaction_id == tx.id
               end
             )
           )
         end
       )
  end

  def get_graph_data_for_address(address) do
    query = from h in History,
                 where: h.address_hash == ^address,
                 order_by: [
                   desc: h.block_height
                 ],
                 limit: 25,
                 select: map(h, [:balance])

    Repo.all(query)
    |> check_result
  end

  defp check_result([]) do
    nil
  end
  defp check_result(list) do
    list
    |> Enum.map(fn %{:balance => b} -> filter_balance(b) end)
  end

  defp filter_balance(nil) do
    nil
  end
  defp filter_balance(balance) do
    balance
    |> Map.to_list()
    |> Enum.reduce(
         %{:time => 0, :assets => []},
         fn ({asset_hash, %{"amount" => amount, "time" => time}}, %{
           :assets => assets
         }) ->
           %{
             :time => time,
             :assets => [
               %{
                 ChainAssets.get_asset_name_by_hash(asset_hash) => amount
               } | assets
             ]
           }
         end
       )
  end

end

defmodule Neoscan.BalanceHistories do
  @moduledoc false

  import Ecto.Query, warn: false
  alias Neoscan.Repo
  alias Neoscan.BalanceHistories.History
  alias Neoscan.Transactions
  alias Neoscan.Transactions.Transaction
  alias Neoscan.ChainAssets

  @doc """
  Returns an `%Ecto.Changeset{}` for tracking address history changes.

  ## Examples

      iex> change_history(history)
      %Ecto.Changeset{source: %History{}}

  """
  def change_history(%History{} = history, address, attrs) do
    History.changeset(history, address, attrs)
  end

  #add a transaction history into an address
  def add_tx_id(attrs, txid, index, time) do
    new_tx = %{
      :txid => txid,
      :balance => attrs.balance,
      :block_height => index,
      :time => time
    }
    %{attrs | tx_ids: new_tx}
  end

  @doc """
  Count total history points for an address.

  ## Examples

      iex> count_histories_for_Address(address_hash)
      50

  """
  def count_hist_for_address(address_hash) do
    query = from h in History,
                 where: h.address_hash == ^address_hash
    Repo.aggregate(query, :count, :id)
  end

  def paginate_history_transactions(address_hash, pag) do
    his_query = from h in History,
                  where: h.address_hash == ^address_hash,
                  order_by: [
                    desc: h.block_height
                  ],
                  select: %{
                    txid: h.txid
                  },
                  limit: 15

    histories = Repo.paginate(his_query, page: pag, page_size: 15)
                |> Enum.map(fn %{:txid => txid} -> txid end)

    transaction_query = from e in Transaction,
                             order_by: [
                               desc: e.block_height
                             ],
                             where: e.txid in ^histories,
                             select: %{
                               :id => e.id,
                               :type => e.type,
                               :time => e.time,
                               :txid => e.txid,
                               :block_height => e.block_height,
                               :block_hash => e.block_hash,
                               :vin => e.vin,
                               :claims => e.claims,
                               :sys_fee => e.sys_fee,
                               :net_fee => e.net_fee,
                               :size => e.size,
                               :asset => e.asset,
                             }

    transactions = Repo.all(transaction_query)
    vouts = Enum.map(transactions, fn tx -> tx.id end)
            |> Transactions.get_transactions_vouts

    transactions
    |> Enum.map(
         fn tx ->
           Map.put(
             tx,
             :vouts,
             Enum.filter(
               vouts,
               fn vout ->
                 vout.transaction_id == tx.id
               end
             )
           )
         end
       )
  end

  def get_graph_data_for_address(address) do
    query = from h in History,
                 where: h.address_hash == ^address,
                 order_by: [
                   desc: h.block_height
                 ],
                 limit: 25,
                 select: map(h, [:balance])

    Repo.all(query)
    |> check_result
  end

  defp check_result([]) do
    nil
  end
  defp check_result(list) do
    list
    |> Enum.map(fn %{:balance => b} -> filter_balance(b) end)
  end

  defp filter_balance(nil) do
    nil
  end
  defp filter_balance(balance) do
    balance
    |> Map.to_list()
    |> Enum.reduce(
         %{:time => 0, :assets => []},
         fn ({asset_hash, %{"amount" => amount, "time" => time}}, %{
           :assets => assets
         }) ->
           %{
             :time => time,
             :assets => [
               %{
                 ChainAssets.get_asset_name_by_hash(asset_hash) => amount
               } | assets
             ]
           }
         end
       )
  end

end


Properly set settings description

Properly set settings description

require Logger

defmodule Serverboards.Settings do
  @doc ~S"""
  Serverboards keeps almost all configuration in datbase to allow easy change
  from UI.

  This module keeps all settings related acesses and changes.

  Each subsection may have specific permissions required.
  """
  import Serverboards.Plugin
  alias Serverboards.Repo
  alias Serverboards.Settings.Model

  def start_link(options) do
    {:ok, es} = EventSourcing.start_link [name: :settings] ++ options
    {:ok, _rpc} = Serverboards.Settings.RPC.start_link

    setup_eventsourcing(es)

    {:ok, es}
  end

  def setup_eventsourcing(es) do
    import EventSourcing

    subscribe es, :update_settings, fn [section, data], _me ->
      update_real(section, data)
    end
    subscribe es, :update_user_settings, fn [email, section, data], _me ->
      update_user_real(email, section, data)
    end

    EventSourcing.Model.subscribe :settings, :settings, Serverboards.Repo
  end

  def update(section, attributes, me) do
    if "settings.update" in me.perms do
      EventSourcing.dispatch(:settings, :update_settings, [section, attributes], me.email)
      :ok
    else
      {:error, :permission_denied}
    end
  end

  def update_real(section, data) do
    #Logger.info("Update settings, #{section}: #{inspect data}")
    case Repo.get_by(Model.Settings, section: section) do
      nil ->
        Repo.insert( %Model.Settings{section: section, data: data} )
      sec ->
        #Logger.debug("#{inspect sec}")
        Repo.update( Model.Settings.changeset(sec, %{data: data}) )
    end
    MOM.Channel.send(:settings, %MOM.Message{payload: %{ type: :update, section: section, data: data }})
    :ok
  end

  def user_update(email, section, data, me) do
    EventSourcing.dispatch(:settings, :update_user_settings, [email, section, data], me)
    :ok
  end
  def update_user_real(email, section, nil) do
    import Ecto.Query

    query = from s in Model.UserSettings,
            join: u in Serverboards.Auth.Model.User,
              on: u.id == s.user_id,
           where: u.email == ^email and s.section == ^section

    Repo.delete_all( query )
  end
  def update_user_real(email, section, data) do
    import Ecto.Query
    [user] = Repo.all(from u in Serverboards.Auth.Model.User, where: u.email == ^email)
    user_id = user.id
    #Logger.info("Update settings, #{section}: #{inspect data}")
    case Repo.get_by(Model.UserSettings, section: section, user_id: user_id) do
      nil ->
        Repo.insert( %Model.UserSettings{section: section, data: data, user_id: user_id} )
      sec ->
        #Logger.debug("#{inspect sec}")
        Repo.update( Model.UserSettings.changeset(sec, %{data: data}) )
    end
    MOM.Channel.send(:user_settings, %MOM.Message{payload: %{ type: :update, user: user, section: section, data: data }})
    :ok
  end

  @doc ~S"""
    Returns a list with all settings sections, with the fields and current values.

    Passwords (fields _pw) are not returned.

    ## Example:

      iex> settings = all_settings(Test.User.system)
      iex> (Enum.count settings) > 0
      true
  """
  def all_settings(me) do
    if "settings.view" in me.perms do
      all_values = Repo.all(Model.Settings) |> Enum.map(fn s -> {s.section,s.data} end)
      all_values = Map.new( all_values )
      #Logger.info("all_values #{inspect all_values}")

      # Foe each component and field, gets stored values and put them at "value"
      Serverboards.Plugin.Registry.filter_component(type: "settings")
        |> Enum.map(fn settings ->
          id = settings.id
          fields = settings.extra["fields"]
          values = Map.get(all_values, id, %{})
          fields = Enum.map(fields, fn f ->
            name = Map.get(f, "name", "")
            if String.ends_with? name, "_pw" do
              Map.put(f, "value", "")
            else
              Map.put(f, "value", Map.get( values, name, nil ))
            end
          end)
          %{
            name: settings.name,
            id: id,
            fields: fields,
            description: settings.description,
            order: settings.extra["order"] || 0
           }
        end)
    else
      {:error, :permission_denied}
    end
  end

  @doc ~S"""
  Returns the full config of a given setting. There is no hidding of
  _pw fields. May require special perms.
  """
  def get(id) do
    import Ecto.Query
    case Repo.all(from s in Model.Settings, where: s.section == ^id) do
      [] ->
        {:error, :not_found}
      [other] ->
        {:ok, other.data}
    end
  end
  def get(id, default) do
    case get(id) do
      {:error, :not_found} -> default
      {:ok, o} -> o
    end
  end

  @doc ~S"""
  Gets data from a given user, or nil if not
  """
  def user_get(email, section) do
    import Ecto.Query
    query = from s in Model.UserSettings,
            join: u in Serverboards.Auth.Model.User,
              on: u.id == s.user_id,
           where: u.email == ^email and s.section == ^section,
           select: s.data
    case Repo.all(query) do
      [] -> nil
      [other] -> other
    end
  end
end

require Logger

defmodule Serverboards.Settings do
  @doc ~S"""
  Serverboards keeps almost all configuration in datbase to allow easy change
  from UI.

  This module keeps all settings related acesses and changes.

  Each subsection may have specific permissions required.
  """
  import Serverboards.Plugin
  alias Serverboards.Repo
  alias Serverboards.Settings.Model

  def start_link(options) do
    {:ok, es} = EventSourcing.start_link [name: :settings] ++ options
    {:ok, _rpc} = Serverboards.Settings.RPC.start_link

    setup_eventsourcing(es)

    {:ok, es}
  end

  def setup_eventsourcing(es) do
    import EventSourcing

    subscribe es, :update_settings, fn [section, data], _me ->
      update_real(section, data)
    end
    subscribe es, :update_user_settings, fn [email, section, data], _me ->
      update_user_real(email, section, data)
    end

    EventSourcing.Model.subscribe :settings, :settings, Serverboards.Repo
  end

  def update(section, attributes, me) do
    if "settings.update" in me.perms do
      EventSourcing.dispatch(:settings, :update_settings, [section, attributes], me.email)
      :ok
    else
      {:error, :permission_denied}
    end
  end

  def update_real(section, data) do
    #Logger.info("Update settings, #{section}: #{inspect data}")
    case Repo.get_by(Model.Settings, section: section) do
      nil ->
        Repo.insert( %Model.Settings{section: section, data: data} )
      sec ->
        #Logger.debug("#{inspect sec}")
        Repo.update( Model.Settings.changeset(sec, %{data: data}) )
    end
    MOM.Channel.send(:settings, %MOM.Message{payload: %{ type: :update, section: section, data: data }})
    :ok
  end

  def user_update(email, section, data, me) do
    EventSourcing.dispatch(:settings, :update_user_settings, [email, section, data], me)
    :ok
  end
  def update_user_real(email, section, nil) do
    import Ecto.Query

    query = from s in Model.UserSettings,
            join: u in Serverboards.Auth.Model.User,
              on: u.id == s.user_id,
           where: u.email == ^email and s.section == ^section

    Repo.delete_all( query )
  end
  def update_user_real(email, section, data) do
    import Ecto.Query
    [user] = Repo.all(from u in Serverboards.Auth.Model.User, where: u.email == ^email)
    user_id = user.id
    #Logger.info("Update settings, #{section}: #{inspect data}")
    case Repo.get_by(Model.UserSettings, section: section, user_id: user_id) do
      nil ->
        Repo.insert( %Model.UserSettings{section: section, data: data, user_id: user_id} )
      sec ->
        #Logger.debug("#{inspect sec}")
        Repo.update( Model.UserSettings.changeset(sec, %{data: data}) )
    end
    MOM.Channel.send(:user_settings, %MOM.Message{payload: %{ type: :update, user: user, section: section, data: data }})
    :ok
  end

  @doc ~S"""
    Returns a list with all settings sections, with the fields and current values.

    Passwords (fields _pw) are not returned.

    ## Example:

      iex> settings = all_settings(Test.User.system)
      iex> (Enum.count settings) > 0
      true
  """
  def all_settings(me) do
    if "settings.view" in me.perms do
      all_values = Repo.all(Model.Settings) |> Enum.map(fn s -> {s.section,s.data} end)
      all_values = Map.new( all_values )
      #Logger.info("all_values #{inspect all_values}")

      # Foe each component and field, gets stored values and put them at "value"
      Serverboards.Plugin.Registry.filter_component(type: "settings")
        |> Enum.map(fn settings ->
          id = settings.id
          fields = settings.extra["fields"]
          values = Map.get(all_values, id, %{})
          fields = Enum.map(fields, fn f ->
            name = Map.get(f, "name", "")
            if String.ends_with? name, "_pw" do
              Map.put(f, "value", "")
            else
              Map.put(f, "value", Map.get( values, name, nil ))
            end
          end)
          %{
            name: settings.name,
            id: id,
            fields: fields,
            description: Map.get(settings.extra, "description", ""),
            order: settings.extra["order"] || 0
           }
        end)
    else
      {:error, :permission_denied}
    end
  end

  @doc ~S"""
  Returns the full config of a given setting. There is no hidding of
  _pw fields. May require special perms.
  """
  def get(id) do
    import Ecto.Query
    case Repo.all(from s in Model.Settings, where: s.section == ^id) do
      [] ->
        {:error, :not_found}
      [other] ->
        {:ok, other.data}
    end
  end
  def get(id, default) do
    case get(id) do
      {:error, :not_found} -> default
      {:ok, o} -> o
    end
  end

  @doc ~S"""
  Gets data from a given user, or nil if not
  """
  def user_get(email, section) do
    import Ecto.Query
    query = from s in Model.UserSettings,
            join: u in Serverboards.Auth.Model.User,
              on: u.id == s.user_id,
           where: u.email == ^email and s.section == ^section,
           select: s.data
    case Repo.all(query) do
      [] -> nil
      [other] -> other
    end
  end
end


Regenerate CloudFunctions client (#1347)

# Copyright 2017 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# NOTE: This class is auto generated by the swagger code generator program.
# https://github.com/swagger-api/swagger-codegen.git
# Do not edit the class manually.

defmodule GoogleApi.CloudFunctions.V1.Model.Operation do
  @moduledoc """
  This resource represents a long-running operation that is the result of a network API call.

  ## Attributes

  - done (boolean()): If the value is `false`, it means the operation is still in progress. If `true`, the operation is completed, and either `error` or `response` is available. Defaults to: `null`.
  - error (Status): The error result of the operation in case of failure or cancellation. Defaults to: `null`.
  - metadata (%{optional(String.t) => String.t}): Service-specific metadata associated with the operation.  It typically contains progress information and common metadata such as create time. Some services might not provide such metadata.  Any method that returns a long-running operation should document the metadata type, if any. Defaults to: `null`.
  - name (String.t): The server-assigned name, which is only unique within the same service that originally returns it. If you use the default HTTP mapping, the `name` should have the format of `operations/some/unique/name`. Defaults to: `null`.
  - response (%{optional(String.t) => String.t}): The normal response of the operation in case of success.  If the original method returns no data on success, such as `Delete`, the response is `google.protobuf.Empty`.  If the original method is standard `Get`/`Create`/`Update`, the response should be the resource.  For other methods, the response should have the type `XxxResponse`, where `Xxx` is the original method name.  For example, if the original method name is `TakeSnapshot()`, the inferred response type is `TakeSnapshotResponse`. Defaults to: `null`.
  """

  use GoogleApi.Gax.ModelBase

  @type t :: %__MODULE__{
          :done => any(),
          :error => GoogleApi.CloudFunctions.V1.Model.Status.t(),
          :metadata => map(),
          :name => any(),
          :response => map()
        }

  field(:done)
  field(:error, as: GoogleApi.CloudFunctions.V1.Model.Status)
  field(:metadata, type: :map)
  field(:name)
  field(:response, type: :map)
end

defimpl Poison.Decoder, for: GoogleApi.CloudFunctions.V1.Model.Operation do
  def decode(value, options) do
    GoogleApi.CloudFunctions.V1.Model.Operation.decode(value, options)
  end
end

defimpl Poison.Encoder, for: GoogleApi.CloudFunctions.V1.Model.Operation do
  def encode(value, options) do
    GoogleApi.Gax.ModelBase.encode(value, options)
  end
end

# Copyright 2017 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# NOTE: This class is auto generated by the swagger code generator program.
# https://github.com/swagger-api/swagger-codegen.git
# Do not edit the class manually.

defmodule GoogleApi.CloudFunctions.V1.Model.Operation do
  @moduledoc """
  This resource represents a long-running operation that is the result of a network API call.

  ## Attributes

  - done (boolean()): If the value is `false`, it means the operation is still in progress. If `true`, the operation is completed, and either `error` or `response` is available. Defaults to: `null`.
  - error (Status): The error result of the operation in case of failure or cancellation. Defaults to: `null`.
  - metadata (%{optional(String.t) => String.t}): Service-specific metadata associated with the operation.  It typically contains progress information and common metadata such as create time. Some services might not provide such metadata.  Any method that returns a long-running operation should document the metadata type, if any. Defaults to: `null`.
  - name (String.t): The server-assigned name, which is only unique within the same service that originally returns it. If you use the default HTTP mapping, the `name` should be a resource name ending with `operations/{unique_id}`. Defaults to: `null`.
  - response (%{optional(String.t) => String.t}): The normal response of the operation in case of success.  If the original method returns no data on success, such as `Delete`, the response is `google.protobuf.Empty`.  If the original method is standard `Get`/`Create`/`Update`, the response should be the resource.  For other methods, the response should have the type `XxxResponse`, where `Xxx` is the original method name.  For example, if the original method name is `TakeSnapshot()`, the inferred response type is `TakeSnapshotResponse`. Defaults to: `null`.
  """

  use GoogleApi.Gax.ModelBase

  @type t :: %__MODULE__{
          :done => any(),
          :error => GoogleApi.CloudFunctions.V1.Model.Status.t(),
          :metadata => map(),
          :name => any(),
          :response => map()
        }

  field(:done)
  field(:error, as: GoogleApi.CloudFunctions.V1.Model.Status)
  field(:metadata, type: :map)
  field(:name)
  field(:response, type: :map)
end

defimpl Poison.Decoder, for: GoogleApi.CloudFunctions.V1.Model.Operation do
  def decode(value, options) do
    GoogleApi.CloudFunctions.V1.Model.Operation.decode(value, options)
  end
end

defimpl Poison.Encoder, for: GoogleApi.CloudFunctions.V1.Model.Operation do
  def encode(value, options) do
    GoogleApi.Gax.ModelBase.encode(value, options)
  end
end