This commit is contained in:
Ruidy 2022-02-07 05:25:10 -04:00
parent ddd3b8ed39
commit 94a40f9db0
22 changed files with 913 additions and 0 deletions

View file

@ -0,0 +1,21 @@
{
"blurb": "Learn about processes and process identifiers by writing an embedded system for a Take-A-Number machine.",
"authors": [
"angelikatyborska"
],
"contributors": [
"neenjaw"
],
"files": {
"solution": [
"lib/take_a_number.ex"
],
"test": [
"test/take_a_number_test.exs"
],
"exemplar": [
".meta/exemplar.ex"
]
},
"language_versions": ">=1.10"
}

View file

@ -0,0 +1 @@
{"track":"elixir","exercise":"take-a-number","id":"719d73ca796343d9abdabd381ee39918","url":"https://exercism.org/tracks/elixir/exercises/take-a-number","handle":"rjNemo","is_requester":true,"auto_approve":false}

View file

@ -0,0 +1,4 @@
# Used by "mix format"
[
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
]

24
take-a-number/.gitignore vendored Normal file
View file

@ -0,0 +1,24 @@
# 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 third-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").
nil-*.tar

75
take-a-number/HELP.md Normal file
View file

@ -0,0 +1,75 @@
# Help
## Running the tests
From the terminal, change to the base directory of the exercise then execute the tests with:
```bash
$ mix test
```
This will execute the test file found in the `test` subfolder -- a file ending in `_test.exs`
Documentation:
* [`mix test` - Elixir's test execution tool](https://hexdocs.pm/mix/Mix.Tasks.Test.html)
* [`ExUnit` - Elixir's unit test library](https://hexdocs.pm/ex_unit/ExUnit.html)
## Pending tests
In test suites of practice exercises, all but the first test have been tagged to be skipped.
Once you get a test passing, you can unskip the next one by commenting out the relevant `@tag :pending` with a `#` symbol.
For example:
```elixir
# @tag :pending
test "shouting" do
assert Bob.hey("WATCH OUT!") == "Whoa, chill out!"
end
```
If you wish to run all tests at once, you can include all skipped test by using the `--include` flag on the `mix test` command:
```bash
$ mix test --include pending
```
Or, you can enable all the tests by commenting out the `ExUnit.configure` line in the file `test/test_helper.exs`.
```elixir
# ExUnit.configure(exclude: :pending, trace: true)
```
## Useful `mix test` options
* `test/<FILE>.exs:LINENUM` - runs only a single test, the test from `<FILE>.exs` whose definition is on line `LINENUM`
* `--failed` - runs only tests that failed the last time they ran
* `--max-failures` - the suite stops evaluating tests when this number of test failures
is reached
* `--seed 0` - disables randomization so the tests in a single file will always be ran
in the same order they were defined in
## Submitting your solution
You can submit your solution using the `exercism submit lib/take_a_number.ex` command.
This command will upload your solution to the Exercism website and print the solution page's URL.
It's possible to submit an incomplete solution which allows you to:
- See how others have completed the exercise
- Request help from a mentor
## Need to get help?
If you'd like help solving the exercise, check the following pages:
- The [Elixir track's documentation](https://exercism.org/docs/tracks/elixir)
- [Exercism's support channel on gitter](https://gitter.im/exercism/support)
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
If you're stuck on something, it may help to look at some of the [available resources](https://exercism.org/docs/tracks/elixir/resources) out there where answers might be found.
If you can't find what you're looking for in the documentation, feel free to ask help in the Exercism's BEAM [gitter channel](https://gitter.im/exercism/xerlang).

40
take-a-number/HINTS.md Normal file
View file

@ -0,0 +1,40 @@
# Hints
## General
- Read about processes in the official [Getting Started guide][getting-started-processes].
- Read [this blog post][mullen-processes] about Elixir processes.
## 1. Start the machine
- The machine should run in a new process. There is [a built-in function that starts a new process][kernel-spawn-1].
- You will need another function that the new process will execute.
## 2. Report the machine state
- The machine's process needs to respond to messages.
- There is [a built-in function that waits for a message to arrive in the process's mailbox][kernel-receive].
- There is [a built-in function that sends a message to another process][kernel-send].
- Use recursion to wait for more than one message.
- Pass the machine's state as an argument to the recursive function.
## 3. Give out numbers
- This step is conceptually the same as the previous step. The only difference is the need to update the machine's state.
## 4. Stop the machine
- This step doesn't require sending any messages as a response.
- A process will exit if it has no more code to execute.
- This is a base case of the recursive function.
## 5. Ignore unexpected messages
- This step doesn't require sending any messages as a response.
- You can use `_` to match all messages that didn't match previous patterns.
[getting-started-processes]: https://elixir-lang.org/getting-started/processes.html
[mullen-processes]: https://samuelmullen.com/articles/elixir-processes-send-and-receive/
[kernel-spawn-1]: https://hexdocs.pm/elixir/Kernel.html#spawn/1
[kernel-receive]: https://hexdocs.pm/elixir/Kernel.SpecialForms.html#receive/1
[kernel-send]: https://hexdocs.pm/elixir/Kernel.html#send/2

112
take-a-number/README.md Normal file
View file

@ -0,0 +1,112 @@
# Take-A-Number
Welcome to Take-A-Number on Exercism's Elixir Track.
If you need help running the tests or submitting your code, check out `HELP.md`.
If you get stuck on the exercise, check out `HINTS.md`, but try and solve it without using those first :)
## Introduction
## Processes
In Elixir, all code runs inside processes.
By default, a function will execute in the same process from which it was called. When you need to explicitly run a certain function in a new process, use `spawn/1`:
```elixir
spawn(fn -> 2 + 2 end)
# => #PID<0.125.0>
```
`spawn/1` creates a new process that executes the given function and returns a _process identifier_ (PID). The new process will stay alive as long as the function executes, and then silently exit.
Elixir's processes should not be confused with operating system processes. Elixir's processes use much less memory and CPU. It's perfectly fine to have Elixir applications that run hundreds of Elixir processes.
### Messages
Processes do not directly share information with one another. Processes _send and receive messages_ to share data.
You can send a message to any process with `send/2`. The first argument to `send/2` is the PID of the recipient, the second argument is the message.
A message can be of any type. Often it consists of atoms and tuples. If you want to get a response, you should include the PID of the sender somewhere in the message. You can get the PID of the current process with `self()`.
`send/2` does not check if the message was received by the recipient, nor if the recipient is still alive. The message ends up in the recipient's _mailbox_ and it will only be read if and when the recipient explicitly asks to _receive messages_.
A message can be read from a mailbox using the `receive/1` macro. It accepts a `do` block that can pattern match on the messages.
```elixir
receive do
{:ping, sender_pid} -> send(sender_pid, :pong)
:do_nothing -> nil
end
```
`receive/1` will take _one message_ from the mailbox that matches any of the given patterns and execute the expression given for that pattern. If there are no messages in the mailbox, or none of messages in the mailbox match any of the patterns, `receive/1` is going to wait for one.
### Receive loop
If you want to receive more than one message, you need to call `receive/1` recursively. It is a common pattern to implement a recursive function, for example named `loop`, that calls `receive/1`, does something with the message, and then calls itself to wait for more messages. If you need to carry some state from one `receive/1` call to another, you can do it by passing an argument to that `loop` function.
## PIDs
Process identifiers are their own data type. They function as _mailbox addresses_ - if you have a process's PID, you can send a message to that process. PIDs are usually created indirectly, as a return value of functions that create new processes, like `spawn`.
## Instructions
You are writing an embedded system for a Take-A-Number machine. It is a very simple model. It can give out consecutive numbers and report what was the last number given out.
## 1. Start the machine
Implement the `start/0` function. It should spawn a new process that has an initial state of `0` and is ready to receive messages. It should return the process's PID.
```elixir
TakeANumber.start()
# => #PID<0.138.0>
```
Note that each time you run this code, the PID may be different.
## 2. Report the machine state
Modify the machine so that it can receive `{:report_state, sender_pid}` messages. It should send its current state (the last given out ticket number) to `sender_pid` and then wait for more messages.
```elixir
machine_pid = TakeANumber.start()
send(machine_pid, {:report_state, self()})
receive do
msg -> msg
end
# => 0
```
## 3. Give out numbers
Modify the machine so that it can receive `{:take_a_number, sender_pid}` messages. It should increase its state by 1, send the new state to `sender_pid`, and then wait for more messages.
```elixir
machine_pid = TakeANumber.start()
send(machine_pid, {:take_a_number, self()})
receive do
msg -> msg
end
# => 1
```
## 4. Stop the machine
Modify the machine so that it can receive a `:stop` message. It should stop waiting for more messages.
## 5. Ignore unexpected messages
Modify the machine so that when it receives an unexpected message, it ignores it and continues waiting for more messages.
## Source
### Created by
- @angelikatyborska
### Contributed to by
- @neenjaw

View file

@ -0,0 +1,23 @@
defmodule TakeANumber do
def start() do
spawn(fn -> listen(0) end)
end
defp listen(state) do
receive do
{:report_state, pid} ->
send(pid, state)
listen(state)
{:take_a_number, pid} ->
send(pid, state + 1)
listen(state + 1)
:stop ->
nil
_ ->
listen(state)
end
end
end

28
take-a-number/mix.exs Normal file
View file

@ -0,0 +1,28 @@
defmodule TakeANumber.MixProject do
use Mix.Project
def project do
[
app: :take_a_number,
version: "0.1.0",
# elixir: "~> 1.10",
start_permanent: Mix.env() == :prod,
deps: deps()
]
end
# Run "mix help compile.app" to learn about applications.
def application do
[
extra_applications: [:logger]
]
end
# Run "mix help deps" to learn about dependencies.
defp deps do
[
# {:dep_from_hexpm, "~> 0.3.0"},
# {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
]
end
end

View file

@ -0,0 +1,89 @@
defmodule TakeANumberTest do
use ExUnit.Case
@tag task_id: 1
test "starts a new process" do
pid = TakeANumber.start()
assert is_pid(pid)
assert pid != self()
assert pid != TakeANumber.start()
end
@tag task_id: 2
test "reports its own state" do
pid = TakeANumber.start()
send(pid, {:report_state, self()})
assert_receive 0
end
@tag task_id: 2
test "does not shut down after reporting its own state" do
pid = TakeANumber.start()
send(pid, {:report_state, self()})
assert_receive 0
send(pid, {:report_state, self()})
assert_receive 0
end
@tag task_id: 3
test "gives out a number" do
pid = TakeANumber.start()
send(pid, {:take_a_number, self()})
assert_receive 1
end
@tag task_id: 3
test "gives out many consecutive numbers" do
pid = TakeANumber.start()
send(pid, {:take_a_number, self()})
assert_receive 1
send(pid, {:take_a_number, self()})
assert_receive 2
send(pid, {:take_a_number, self()})
assert_receive 3
send(pid, {:report_state, self()})
assert_receive 3
send(pid, {:take_a_number, self()})
assert_receive 4
send(pid, {:take_a_number, self()})
assert_receive 5
send(pid, {:report_state, self()})
assert_receive 5
end
@tag task_id: 4
test "stops" do
pid = TakeANumber.start()
assert Process.alive?(pid)
send(pid, {:report_state, self()})
assert_receive 0
send(pid, :stop)
send(pid, {:report_state, self()})
refute_receive 0
refute Process.alive?(pid)
end
@tag task_id: 5
test "ignores unexpected messages and keeps working" do
pid = TakeANumber.start()
send(pid, :hello?)
send(pid, "I want to speak with the manager")
send(pid, {:take_a_number, self()})
assert_receive 1
send(pid, {:report_state, self()})
assert_receive 1
assert Keyword.get(Process.info(pid), :message_queue_len) == 0
end
end

View file

@ -0,0 +1,2 @@
ExUnit.start()
ExUnit.configure(exclude: :pending, trace: true, seed: 0)

View file

@ -0,0 +1,21 @@
{
"blurb": "Learn about keyword lists by providing wine suggestions to the customers in your restaurant.",
"authors": [
"angelikatyborska"
],
"contributors": [
"neenjaw"
],
"files": {
"solution": [
"lib/wine_cellar.ex"
],
"test": [
"test/wine_cellar_test.exs"
],
"exemplar": [
".meta/exemplar.ex"
]
},
"language_versions": ">=1.10"
}

View file

@ -0,0 +1 @@
{"track":"elixir","exercise":"wine-cellar","id":"d5032be81ac44be69340ea77c3cd83d8","url":"https://exercism.org/tracks/elixir/exercises/wine-cellar","handle":"rjNemo","is_requester":true,"auto_approve":false}

View file

@ -0,0 +1,4 @@
# Used by "mix format"
[
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
]

24
wine-cellar/.gitignore vendored Normal file
View file

@ -0,0 +1,24 @@
# 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 third-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").
nil-*.tar

75
wine-cellar/HELP.md Normal file
View file

@ -0,0 +1,75 @@
# Help
## Running the tests
From the terminal, change to the base directory of the exercise then execute the tests with:
```bash
$ mix test
```
This will execute the test file found in the `test` subfolder -- a file ending in `_test.exs`
Documentation:
* [`mix test` - Elixir's test execution tool](https://hexdocs.pm/mix/Mix.Tasks.Test.html)
* [`ExUnit` - Elixir's unit test library](https://hexdocs.pm/ex_unit/ExUnit.html)
## Pending tests
In test suites of practice exercises, all but the first test have been tagged to be skipped.
Once you get a test passing, you can unskip the next one by commenting out the relevant `@tag :pending` with a `#` symbol.
For example:
```elixir
# @tag :pending
test "shouting" do
assert Bob.hey("WATCH OUT!") == "Whoa, chill out!"
end
```
If you wish to run all tests at once, you can include all skipped test by using the `--include` flag on the `mix test` command:
```bash
$ mix test --include pending
```
Or, you can enable all the tests by commenting out the `ExUnit.configure` line in the file `test/test_helper.exs`.
```elixir
# ExUnit.configure(exclude: :pending, trace: true)
```
## Useful `mix test` options
* `test/<FILE>.exs:LINENUM` - runs only a single test, the test from `<FILE>.exs` whose definition is on line `LINENUM`
* `--failed` - runs only tests that failed the last time they ran
* `--max-failures` - the suite stops evaluating tests when this number of test failures
is reached
* `--seed 0` - disables randomization so the tests in a single file will always be ran
in the same order they were defined in
## Submitting your solution
You can submit your solution using the `exercism submit lib/wine_cellar.ex` command.
This command will upload your solution to the Exercism website and print the solution page's URL.
It's possible to submit an incomplete solution which allows you to:
- See how others have completed the exercise
- Request help from a mentor
## Need to get help?
If you'd like help solving the exercise, check the following pages:
- The [Elixir track's documentation](https://exercism.org/docs/tracks/elixir)
- [Exercism's support channel on gitter](https://gitter.im/exercism/support)
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
If you're stuck on something, it may help to look at some of the [available resources](https://exercism.org/docs/tracks/elixir/resources) out there where answers might be found.
If you can't find what you're looking for in the documentation, feel free to ask help in the Exercism's BEAM [gitter channel](https://gitter.im/exercism/xerlang).

33
wine-cellar/HINTS.md Normal file
View file

@ -0,0 +1,33 @@
# Hints
## General
- Read about keyword lists in the official [Getting Started guide][getting-started-keyword-lists].
- Read about keyword lists on [elixirschool.com][elixir-school-keyword-lists].
- Take a look at the [documentation of the `Keyword` module][keyword].
## 1. Explain wine colors
- You need to write the information given in the table as a keyword list.
- Take a look at some [examples][keyword-examples] of how to define a keyword list.
## 2. Get all wines of a given color
- There is a [built-in function][keyword-get-values] for getting the list of all values for a given key.
## 3. Get all wines of a given color bottled in a given year
- There is a [built-in function][keyword-get] for getting a single value for a given key.
- You do not need to implement the filtering of bottles on your own. You just need to conditionally use the already-implemented `filter_by_year/2` function.
## 4. Get all wines of a given color bottled in a given country
- There is a [built-in function][keyword-get] for getting a single value for a given key.
- You do not need to implement the filtering of bottles on your own. You just need to conditionally use the already-implemented `filter_by_country/2` function.
[getting-started-keyword-lists]: https://elixir-lang.org/getting-started/keywords-and-maps.html#keyword-lists
[elixir-school-keyword-lists]: https://elixirschool.com/en/lessons/basics/collections/#keyword-lists
[keyword]: https://hexdocs.pm/elixir/Keyword.html
[keyword-get-values]: https://hexdocs.pm/elixir/Keyword.html#get_values/2
[keyword-get]: https://hexdocs.pm/elixir/Keyword.html#get/3
[keyword-examples]: https://hexdocs.pm/elixir/Keyword.html#module-examples

130
wine-cellar/README.md Normal file
View file

@ -0,0 +1,130 @@
# Wine Cellar
Welcome to Wine Cellar on Exercism's Elixir Track.
If you need help running the tests or submitting your code, check out `HELP.md`.
If you get stuck on the exercise, check out `HINTS.md`, but try and solve it without using those first :)
## Introduction
## Keyword Lists
Keyword lists are a key-value data structure.
```elixir
[month: "April", year: 2018]
```
Keyword lists are lists of `{key, value}` tuples, and can also be written as such, but the shorter syntax is more widely used.
```elixir
[month: "April"] == [{:month, "April"}]
# => true
```
Keys in a keyword list must be atoms, but the values can be anything. Each key can be used more than once. The key-value pairs in a keyword list are ordered.
You can work with keyword lists using the same approaches as for lists, or you can use the `Keyword` module.
## Instructions
You are the manager of a fancy restaurant that has a sizable wine cellar. A lot of your customers are demanding wine enthusiasts. Finding the right bottle of wine for a particular customer is not an easy task.
As a tech-savvy restaurant owner, you decided to speed up the wine selection process by writing an app that will let guests filter your wines by their preferences.
## 1. Explain wine colors
On the welcome screen of your app, you want to display a short explanation of each wine color.
Implement the `WineCellar.explain_colors/0` function. It takes no arguments and returns a keyword list with wine colors as keys and explanations as values.
| Color | Explanation |
| -------- | -------------------------------------------------------------------------- |
| `:white` | Fermented without skin contact. |
| `:red` | Fermented with skin contact using dark-colored grapes. |
| `:rose` | Fermented with some skin contact, but not enough to qualify as a red wine. |
## 2. Get all wines of a given color
A bottle of wine is represented as a 3-tuple of grape variety, year, and country of origin. The wines are stored by wine color in a keyword list.
```elixir
[
white: {"Chardonnay", 2015, "Italy"},
white: {"Pinot grigio", 2017, "Germany"},
red: {"Pinot noir", 2016, "France"},
rose: {"Dornfelder", 2018, "Germany"}
]
```
Implement the `WineCellar.filter/3` function. It should take a keyword list of wines, a color atom and a keyword list of options, with a default value of `[]`. The function should return a list of wines of a given color.
```elixir
WineCellar.filter(
[
white: {"Chardonnay", 2015, "Italy"},
white: {"Pinot grigio", 2017, "Germany"},
red: {"Pinot noir", 2016, "France"},
rose: {"Dornfelder", 2018, "Germany"}
],
:white
)
# => [
# {"Chardonnay", 2015, "Italy"},
# {"Pinot grigio", 2017, "Germany"}
# ]
```
## 3. Get all wines of a given color bottled in a given year
Extend the `WineCellar.filter/3` function. When given a `:year` option, the function should return a list of wines of a given color from a given year.
Use the already-implemented `WineCellar.filter_by_year/2` function. It takes a list of wines and a year as arguments and returns a list of wines from a given year.
```elixir
WineCellar.filter(
[
white: {"Chardonnay", 2015, "Italy"},
white: {"Pinot grigio", 2017, "Germany"},
red: {"Pinot noir", 2016, "France"},
rose: {"Dornfelder", 2018, "Germany"}
],
:white,
year: 2015
)
# => [
# {"Chardonnay", 2015, "Italy"}
# ]
```
## 4. Get all wines of a given color bottled in a given country
Extend the `WineCellar.filter/3` function. When given a `:country` option, the function should return a list of wines of a given color from a given country.
Use the already-implemented `WineCellar.filter_by_country/2` function. It takes a list of wines and a country as arguments and returns a list of wines from a given country.
Make sure that the function works when given both the `:year` and the `:country` option, in any order.
```elixir
WineCellar.filter(
[
white: {"Chardonnay", 2015, "Italy"},
white: {"Pinot grigio", 2017, "Germany"},
red: {"Pinot noir", 2016, "France"},
rose: {"Dornfelder", 2018, "Germany"}
],
:white,
year: 2015,
country: "Germany"
)
# => []
```
## Source
### Created by
- @angelikatyborska
### Contributed to by
- @neenjaw

View file

@ -0,0 +1,58 @@
defmodule WineCellar do
def explain_colors(),
do: [
white: "Fermented without skin contact.",
red: "Fermented with skin contact using dark-colored grapes.",
rose: "Fermented with some skin contact, but not enough to qualify as a red wine."
]
def filter(cellar, color, opts \\ [])
def filter([], _, _), do: []
def filter(cellar, color, []), do: filter_by_color(cellar, color)
def filter(cellar, color, year: year),
do:
filter_by_color(cellar, color)
|> filter_by_year(year)
def filter(cellar, color, country: country),
do:
filter_by_color(cellar, color)
|> filter_by_country(country)
def filter(cellar, color, opts) do
country = Keyword.get(opts, :country)
year = Keyword.get(opts, :year)
filter_by_color(cellar, color)
|> filter_by_country(country)
|> filter_by_year(year)
end
defp filter_by_color(cellar, color), do: Keyword.get_values(cellar, color)
# The functions below do not need to be modified.
defp filter_by_year(wines, year)
defp filter_by_year([], _year), do: []
defp filter_by_year([{_, year, _} = wine | tail], year) do
[wine | filter_by_year(tail, year)]
end
defp filter_by_year([{_, _, _} | tail], year) do
filter_by_year(tail, year)
end
defp filter_by_country(wines, country)
defp filter_by_country([], _country), do: []
defp filter_by_country([{_, _, country} = wine | tail], country) do
[wine | filter_by_country(tail, country)]
end
defp filter_by_country([{_, _, _} | tail], country) do
filter_by_country(tail, country)
end
end

28
wine-cellar/mix.exs Normal file
View file

@ -0,0 +1,28 @@
defmodule WineCellar.MixProject do
use Mix.Project
def project do
[
app: :wine_cellar,
version: "0.1.0",
# elixir: "~> 1.10",
start_permanent: Mix.env() == :prod,
deps: deps()
]
end
# Run "mix help compile.app" to learn about applications.
def application do
[
extra_applications: [:logger]
]
end
# Run "mix help deps" to learn about dependencies.
defp deps do
[
# {:dep_from_hexpm, "~> 0.3.0"},
# {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
]
end
end

View file

@ -0,0 +1,2 @@
ExUnit.start()
ExUnit.configure(exclude: :pending, trace: true, seed: 0)

View file

@ -0,0 +1,118 @@
defmodule WineCellarTest do
use ExUnit.Case
describe "explain_colors/0" do
@tag task_id: 1
test "returns a keyword list" do
assert WineCellar.explain_colors() == [
white: "Fermented without skin contact.",
red: "Fermented with skin contact using dark-colored grapes.",
rose: "Fermented with some skin contact, but not enough to qualify as a red wine."
]
end
end
describe "filter/3" do
@tag task_id: 2
test "works for empty cellar" do
assert WineCellar.filter([], :rose) == []
end
@tag task_id: 2
test "returns all wines of a chosen color" do
cellar = [
white: {"Chardonnay", 2015, "Italy"},
white: {"Chardonnay", 2014, "France"},
rose: {"Dornfelder", 2018, "Germany"},
red: {"Merlot", 2015, "France"},
white: {"Riesling ", 2017, "Germany"},
white: {"Pinot grigio", 2015, "Germany"},
red: {"Pinot noir", 2016, "France"},
red: {"Pinot noir", 2013, "Italy"}
]
assert WineCellar.filter(cellar, :white) == [
{"Chardonnay", 2015, "Italy"},
{"Chardonnay", 2014, "France"},
{"Riesling ", 2017, "Germany"},
{"Pinot grigio", 2015, "Germany"}
]
assert WineCellar.filter(cellar, :rose) == [{"Dornfelder", 2018, "Germany"}]
end
@tag task_id: 3
test "filters wines of chosen color by year" do
cellar = [
white: {"Chardonnay", 2015, "Italy"},
white: {"Chardonnay", 2014, "France"},
rose: {"Dornfelder", 2018, "Germany"},
red: {"Merlot", 2015, "France"},
white: {"Riesling ", 2017, "Germany"},
white: {"Pinot grigio", 2015, "Germany"},
red: {"Pinot noir", 2016, "France"},
red: {"Pinot noir", 2013, "Italy"}
]
assert WineCellar.filter(cellar, :white, year: 2015) == [
{"Chardonnay", 2015, "Italy"},
{"Pinot grigio", 2015, "Germany"}
]
end
@tag task_id: 4
test "filters wines of chosen color by country" do
cellar = [
white: {"Chardonnay", 2015, "Italy"},
white: {"Chardonnay", 2014, "France"},
rose: {"Dornfelder", 2018, "Germany"},
red: {"Merlot", 2015, "France"},
white: {"Riesling ", 2017, "Germany"},
white: {"Pinot grigio", 2015, "Germany"},
red: {"Pinot noir", 2016, "France"},
red: {"Pinot noir", 2013, "Italy"}
]
assert WineCellar.filter(cellar, :red, country: "France") == [
{"Merlot", 2015, "France"},
{"Pinot noir", 2016, "France"}
]
end
@tag task_id: 4
test "filters wines of chosen color by year and country" do
cellar = [
white: {"Chardonnay", 2015, "Italy"},
white: {"Chardonnay", 2014, "France"},
rose: {"Dornfelder", 2018, "Germany"},
red: {"Merlot", 2015, "France"},
white: {"Riesling ", 2017, "Germany"},
white: {"Pinot grigio", 2015, "Germany"},
red: {"Pinot noir", 2016, "France"},
red: {"Pinot noir", 2013, "Italy"}
]
assert WineCellar.filter(cellar, :white, year: 2015, country: "Germany") == [
{"Pinot grigio", 2015, "Germany"}
]
end
@tag task_id: 4
test "filters wines of chosen color by country and year" do
cellar = [
white: {"Chardonnay", 2015, "Italy"},
white: {"Chardonnay", 2014, "France"},
rose: {"Dornfelder", 2018, "Germany"},
red: {"Merlot", 2015, "France"},
white: {"Riesling ", 2017, "Germany"},
white: {"Pinot grigio", 2015, "Germany"},
red: {"Pinot noir", 2016, "France"},
red: {"Pinot noir", 2013, "Italy"}
]
assert WineCellar.filter(cellar, :red, country: "France", year: 2015) == [
{"Merlot", 2015, "France"}
]
end
end
end