Build FunPark: Model Real-World Data
Mix.install([
{:fun_park,
git: "https://github.com/JKWA/funpark_notebooks.git",
branch: "main"
}
])
Advanced Functional Programming with Elixir
|
Interactive Examples from Chapter 1 Advanced Functional Programming with Elixir. |
Define the Ride Model
Rides have core attributes: unique ID, name, height/age requirements, and can go offline. They also have experience tags like :dark
, :thrill
, or :water
.
```elixir
defmodule FunPark.Ride do
defstruct id: nil,
name: "Unknown Ride",
min_age: 0,
min_height: 0,
wait_time: 0,
online: true,
tags: []
def make(name, opts \\ []) when is_binary(name) do
%__MODULE__{
id: :erlang.unique_integer([:positive]),
name: name,
min_age: Keyword.get(opts, :min_age, 0),
min_height: Keyword.get(opts, :min_height, 0),
wait_time: Keyword.get(opts, :wait_time, 0),
online: Keyword.get(opts, :online, true),
tags: Keyword.get(opts, :tags, [])
}
end
end
```
Create a family-friendly ride:
FunPark.Ride.make("Tea Cup", wait_time: 10, tags: [:family_friendly])
Create a more restricted ride:
dark_mansion = FunPark.Ride.make(
"Dark Mansion",
min_age: 14,
tags: [:dark]
)
Implement Fast Passes for Priority Access
FastPasses manage demand for popular rides. Each pass is tied to a specific ride and time.
```elixir
defmodule FunPark.FastPass do
alias FunPark.Ride
defstruct id: nil,
ride: nil,
time: nil
def make(%Ride{} = ride, %DateTime{} = time) do
%__MODULE__{
id: :erlang.unique_integer([:positive]),
ride: ride,
time: time
}
end
end
```
Create a time:
datetime = DateTime.new!(~D[2025-06-01], ~T[13:00:00])
Create a fast pass for the Dark Mansion:
fast_pass = FunPark.FastPass.make(dark_mansion, datetime)
Model the Patrons
These are called “patrons”. Patrons have personal attributes, ticket tiers, fast passes, reward points, and preferences.
```elixir
defmodule FunPark.Patron do
defstruct id: nil,
name: nil,
age: 0,
height: 0,
ticket_tier: :basic,
fast_passes: [],
reward_points: 0,
likes: [],
dislikes: []
def make(name, age, height, opts \\ [])
when is_bitstring(name) and
is_integer(age) and
is_integer(height) and
age > 0 and
height > 0 do
%__MODULE__{
id: :erlang.unique_integer([:positive]),
name: name,
age: age,
height: height,
ticket_tier: Keyword.get(opts, :ticket_tier, :basic),
fast_passes: Keyword.get(opts, :fast_passes, []),
reward_points: Keyword.get(opts, :reward_points, 0),
likes: Keyword.get(opts, :likes, []),
dislikes: Keyword.get(opts, :dislikes, [])
}
end
end
```
Create a patron named Alice with a FastPass:
FunPark.Patron.make("Alice", 15, 120, fast_passes: [fast_pass])