Skip to content

Commit

Permalink
chapter 3
Browse files Browse the repository at this point in the history
  • Loading branch information
Tajinder Chumber committed Aug 15, 2018
1 parent 9806fc6 commit 470baf7
Show file tree
Hide file tree
Showing 12 changed files with 263 additions and 0 deletions.
43 changes: 43 additions & 0 deletions chapter3/excersises.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
defmodule Exercise do
def run() do
pboss = spawn(ProcessBoss, :loop, [])
pid1 = spawn(Process1, :loop, [])
pid2 = spawn(Process2, :loop, [])

send pid1, {pboss, :ping}
send pid2, {pboss, :pong}
end
end

defmodule ProcessBoss do
def loop do
receive do
{:ok, msg, from: from} -> IO.inspect("#{from} says #{msg}")
_ -> IO.puts "Unknow Message"
end
loop()
end
end

defmodule Process1 do
def loop do
receive do
{sender_pid, :ping} ->
send(sender_pid, {:ok, :pong, from: :ping})
_ ->
IO.puts "Unknow Message"
end
loop()
end
end

defmodule Process2 do
def loop do
receive do
{sender_pid, :pong} ->
send(sender_pid, {:ok, :ping, from: :pong})
_ -> IO.puts "Unknow Message"
end
loop()
end
end
4 changes: 4 additions & 0 deletions chapter3/metex/.formatter.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Used by "mix format"
[
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
]
25 changes: 25 additions & 0 deletions chapter3/metex/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# The directory Mix will write compiled artifacts to.
/_build/

# If you run "mix test --cover", coverage assets end up here.
/cover/

# The directory Mix downloads your dependencies sources to.
/deps/

# Where 3rd-party dependencies like ExDoc output generated docs.
/doc/

# Ignore .fetch files in case you like to edit your project deps locally.
/.fetch

# If the VM crashes, it generates a dump, let's ignore it too.
erl_crash.dump

# Also ignore archive artifacts (built via "mix archive.build").
*.ez

# Ignore package tarball (built via "mix hex.build").
metex-*.tar

.elixir_ls/
21 changes: 21 additions & 0 deletions chapter3/metex/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Metex

**TODO: Add description**

## Installation

If [available in Hex](https://hex.pm/docs/publish), the package can be installed
by adding `metex` to your list of dependencies in `mix.exs`:

```elixir
def deps do
[
{:metex, "~> 0.1.0"}
]
end
```

Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
be found at [https://hexdocs.pm/metex](https://hexdocs.pm/metex).

30 changes: 30 additions & 0 deletions chapter3/metex/config/config.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# This file is responsible for configuring your application
# and its dependencies with the aid of the Mix.Config module.
use Mix.Config

# This configuration is loaded before any dependency and is restricted
# to this project. If another project depends on this project, this
# file won't be loaded nor affect the parent project. For this reason,
# if you want to provide default values for your application for
# 3rd-party users, it should be done in your "mix.exs" file.

# You can configure your application as:
#
# config :metex, key: :value
#
# and access this configuration in your application as:
#
# Application.get_env(:metex, :key)
#
# You can also configure a 3rd-party app:
#
# config :logger, level: :info
#

# It is also possible to import configuration files, relative to this
# directory. For example, you can emulate configuration per environment
# by uncommenting the line below and defining dev.exs, test.exs and such.
# Configuration from the imported file will override the ones defined
# here (which is why it is important to import them last).
#
# import_config "#{Mix.env()}.exs"
16 changes: 16 additions & 0 deletions chapter3/metex/lib/coordinator.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
defmodule Metex.Coordinator do
def loop(results \\ [], results_expected) do
receive do
{:ok, result} ->
new_results = [result | results]
if results_expected == Enum.count(new_results) do
send self(), :exit
end
loop(new_results, results_expected)
:exit ->
IO.puts(results |> Enum.sort |> Enum.join(", "))
_ ->
loop(results, results_expected)
end
end
end
14 changes: 14 additions & 0 deletions chapter3/metex/lib/metex.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
defmodule Metex do
def temperature_of(cities) do
coordinator_pid =
spawn(Metex.Coordinator, :loop, [[], Enum.count(cities)])

cities |> Enum.each(fn city ->
worker_pid = spawn(Metex.Worker, :loop, [])
send worker_pid, {coordinator_pid, city}
end)
end
end

# cities = ["Singapore", "Monaco", "Vatican City", "Hong Kong", "Macau"]
# Metex.temperature_of(cities)
59 changes: 59 additions & 0 deletions chapter3/metex/lib/worker.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
defmodule Metex.Worker do
def loop do
receive do
{sender_pid, location} ->
send(sender_pid, {:ok, temperature_of(location)})
_ ->
IO.puts "don't know how to process this message"
end
loop()
end

def temperature_of(location) do
result = url_for(location) |> HTTPoison.get |> parse_response
case result do
{:ok, temp} ->
"#{location}: #{temp}°C"
:error ->
"#{location}: not found"
end
end

defp url_for(location) do
location = URI.encode(location)
"http://api.openweathermap.org/data/2.5/weather?q=#{location}&appid=#{apikey()}"
end

defp parse_response({:ok, %HTTPoison.Response{body: body, status_code: 200}}) do
body |> JSON.decode! |> compute_temperature
end

defp parse_response(_) do
:error
end

defp compute_temperature(json) do
try do
temp = (json["main"]["temp"] - 273.15) |> Float.round(1)
{:ok, temp}
rescue
_ -> :error
end
end

defp apikey do
"74148f1e51e4ac1feba5e0d04c2a1ec2"
end
end

# cities = ["Singapore", "Monaco", "Vatican City", "Hong Kong", "Macau"]

# Without Processes
# cities |> Enum.map(fn city -> Metex.Worker.temperature_of(city) end)

# With Processes
# pid = spawn(Metex.Worker, :loop, [])
# cities |> Enum.each(fn city ->
# pid = spawn(Metex.Worker, :loop, [])
# send(pid, {self, city})
# end)
30 changes: 30 additions & 0 deletions chapter3/metex/mix.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
defmodule Metex.MixProject do
use Mix.Project

def project do
[
app: :metex,
version: "0.1.0",
elixir: "~> 1.7",
start_permanent: Mix.env() == :prod,
deps: deps()
]
end

# Run "mix help compile.app" to learn about applications.
def application do
[
extra_applications: [:logger, :httpoison]
]
end

# Run "mix help deps" to learn about dependencies.
defp deps do
[
{:httpoison, "~> 1.2.0"},
{:json, "~> 1.2"}
# {:dep_from_hexpm, "~> 0.3.0"},
# {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"},
]
end
end
12 changes: 12 additions & 0 deletions chapter3/metex/mix.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
%{
"certifi": {:hex, :certifi, "2.3.1", "d0f424232390bf47d82da8478022301c561cf6445b5b5fb6a84d49a9e76d2639", [:rebar3], [{:parse_trans, "3.2.0", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm"},
"hackney": {:hex, :hackney, "1.13.0", "24edc8cd2b28e1c652593833862435c80661834f6c9344e84b6a2255e7aeef03", [:rebar3], [{:certifi, "2.3.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "5.1.2", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"},
"httpoison": {:hex, :httpoison, "1.2.0", "2702ed3da5fd7a8130fc34b11965c8cfa21ade2f232c00b42d96d4967c39a3a3", [:mix], [{:hackney, "~> 1.8", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"},
"idna": {:hex, :idna, "5.1.2", "e21cb58a09f0228a9e0b95eaa1217f1bcfc31a1aaa6e1fdf2f53a33f7dbd9494", [:rebar3], [{:unicode_util_compat, "0.3.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"},
"json": {:hex, :json, "1.2.5", "3682c18c6b07480df2122d0daf5c05457b42c1990f197ce3de53884e8ba834c4", [:mix], [{:benchee, "~> 0.8", [hex: :benchee, repo: "hexpm", optional: true]}, {:benchee_html, "~> 0.1", [hex: :benchee_html, repo: "hexpm", optional: true]}, {:exjsx, "~> 4.0", [hex: :exjsx, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:jsone, "~> 1.4", [hex: :jsone, repo: "hexpm", optional: true]}, {:poison, "~> 3.0", [hex: :poison, repo: "hexpm", optional: true]}, {:tiny, "~> 1.0", [hex: :tiny, repo: "hexpm", optional: true]}], "hexpm"},
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm"},
"mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [:rebar3], [], "hexpm"},
"parse_trans": {:hex, :parse_trans, "3.2.0", "2adfa4daf80c14dc36f522cf190eb5c4ee3e28008fc6394397c16f62a26258c2", [:rebar3], [], "hexpm"},
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [:make, :rebar], [], "hexpm"},
"unicode_util_compat": {:hex, :unicode_util_compat, "0.3.1", "a1f612a7b512638634a603c8f401892afbf99b8ce93a45041f8aaca99cadb85e", [:rebar3], [], "hexpm"},
}
8 changes: 8 additions & 0 deletions chapter3/metex/test/metex_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
defmodule MetexTest do
use ExUnit.Case
doctest Metex

test "greets the world" do
assert Metex.hello() == :world
end
end
1 change: 1 addition & 0 deletions chapter3/metex/test/test_helper.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ExUnit.start()

0 comments on commit 470baf7

Please sign in to comment.