Skip to content
This repository has been archived by the owner on Jun 11, 2023. It is now read-only.

Commit

Permalink
Add docs
Browse files Browse the repository at this point in the history
  • Loading branch information
renatomassaro committed Dec 23, 2017
1 parent 134e684 commit f069b82
Show file tree
Hide file tree
Showing 13 changed files with 252 additions and 57 deletions.
10 changes: 10 additions & 0 deletions lib/entity/henforcer/entity.ex
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ defmodule Helix.Entity.Henforcer.Entity do
@spec owns_component?(Entity.idt, Component.idt, [Component.t] | nil) ::
{true, owns_component_relay}
| owns_component_error
@doc """
Henforces the Entity is the owner of the given component. The third parameter,
`owned`, allows users of this function to pass a previously fetched list of
components owned by the entity (cache).
"""
def owns_component?(entity_id = %Entity.ID{}, component, owned) do
henforce entity_exists?(entity_id) do
owns_component?(relay.entity, component, owned)
Expand Down Expand Up @@ -132,6 +137,11 @@ defmodule Helix.Entity.Henforcer.Entity do
@spec owns_nip?(Entity.idt, Network.id, Network.ip, owned_ncs) ::
{true, owns_nip_relay}
| owns_nip_error
@doc """
Henforces the Entity is the owner of the given NIP (NetworkConnection). The
third parameter, `owned`, allows users of this function to pass a previously
fetched list of NCs owned by the entity (cache).
"""
def owns_nip?(entity_id = %Entity.ID{}, network_id, ip, owned) do
henforce entity_exists?(entity_id) do
owns_nip?(relay.entity, network_id, ip, owned)
Expand Down
4 changes: 3 additions & 1 deletion lib/network/model/network/connection.ex
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ defmodule Helix.Network.Model.Network.Connection do
|> validate_required(@required_fields)
end

@spec update_nic(t, Component.nic | nil) ::
@spec update_nic(t, Component.nic) ::
changeset
def update_nic(nc = %__MODULE__{}, nic = %Component{type: :nic}) do
nc
Expand All @@ -74,6 +74,8 @@ defmodule Helix.Network.Model.Network.Connection do
|> validate_required(@required_fields)
end

@spec update_nic(t, nil) ::
changeset
def update_nic(nc = %__MODULE__{}, nil) do
nc
|> change
Expand Down
19 changes: 17 additions & 2 deletions lib/server/action/flow/server.ex
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,18 @@ defmodule Helix.Server.Action.Flow.Server do
Motherboard.t,
MotherboardAction.motherboard_data,
entity_ncs :: [Network.Connection.t],
relay :: Event.relay
) ::
relay :: Event.relay)
::
update_mobo_result
@doc """
Updates the server motherboard.
`new_mobo_data` holds all information about how the new motherboard should
look like.
Emits `MotherboardUpdatedEvent` in case of success, and
`MotherboardUpdateFailedEvent` otherwise.
"""
def update_mobo(
server = %Server{},
motherboard,
Expand Down Expand Up @@ -91,6 +100,12 @@ defmodule Helix.Server.Action.Flow.Server do

@spec detach_mobo(Server.t, Motherboard.t, Event.relay) ::
detach_mobo_result
@doc """
Detaches the server motherboard.
Emits `MotherboardUpdatedEvent` in case of success, and
`MotherboardUpdateFailedEvent` otherwise.
"""
def detach_mobo(server = %Server{}, motherboard = %Motherboard{}, relay) do
flowing do
with \
Expand Down
23 changes: 23 additions & 0 deletions lib/server/action/motherboard/update.ex
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,13 @@ defmodule Helix.Server.Action.Motherboard.Update do

@spec detach(Motherboard.t) ::
:ok
@doc """
Detaches the `motherboard`.
"""
def detach(motherboard = %Motherboard{}) do
MotherboardInternal.unlink_all(motherboard)

# Network configuration is asynchronous
hespawn fn ->
motherboard
|> MotherboardQuery.get_nics()
Expand All @@ -53,10 +57,20 @@ defmodule Helix.Server.Action.Motherboard.Update do

@spec update(Motherboard.t | nil, motherboard_data, [Network.Connection.t]) ::
{:ok, Motherboard.t, [term]}
@doc """
Updates the motherboard.
First parameter is the current motherboard. If `nil`, a motherboard is being
attached to a server that was currently without motherboard.
Updating a motherboard is - as of now - quite naive: we simply unlink all
existing components and then link what was specified by the user.
"""
def update(nil, mobo_data, entity_ncs) do
{:ok, new_mobo} =
MotherboardInternal.setup(mobo_data.mobo, mobo_data.components)

# Network configuration is asynchronous
hespawn fn ->
update_network_connections(mobo_data, entity_ncs)
end
Expand All @@ -75,6 +89,7 @@ defmodule Helix.Server.Action.Motherboard.Update do
MotherboardInternal.setup(mobo_data.mobo, mobo_data.components)
end

# Network configuration is asynchronous
hespawn fn ->
update_network_connections(mobo_data, entity_ncs)
end
Expand All @@ -84,6 +99,14 @@ defmodule Helix.Server.Action.Motherboard.Update do

@spec update_network_connections(motherboard_data, [Network.Connection.t]) ::
term
docp """
Iterates through the player's network connections (NCs), as well as all NCs
assigned to the new motherboard configuration.
This iteration detects which (if any) NC should be updated, either because it
was previously attached to the motherboard and was removed, or because it was
not previously attached to any mobo but now it is.
"""
defp update_network_connections(mobo_data, entity_ncs) do
ncs = mobo_data.network_connections

Expand Down
22 changes: 22 additions & 0 deletions lib/server/event/motherboard.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@ defmodule Helix.Server.Event.Motherboard do
import Helix.Event

event Updated do
@moduledoc """
`MotherboardUpdatedEvent` is fired when the server motherboard has changed
as a result of a player's action. Changes include removal of the mobo
(detach) as well as (un)linking components.
This data is Notificable, i.e. sent to the Client. The client receives the
new motherboard data through HardwareIndex (same data sent during the
bootstrap step).
"""

alias Helix.Server.Model.Server
alias Helix.Server.Public.Index.Hardware, as: HardwareIndex
Expand Down Expand Up @@ -34,6 +43,11 @@ defmodule Helix.Server.Event.Motherboard do

@event :motherboard_updated

@doc """
The player (server channel with `local` access) receives the full hardware
index, while any remote connection receives only remote data (like total
hardware resources).
"""
def generate_payload(event, %{assigns: %{meta: %{access: :local}}}) do
data = HardwareIndex.render_index(event.index_cache)

Expand All @@ -55,6 +69,11 @@ defmodule Helix.Server.Event.Motherboard do
end

event UpdateFailed do
@moduledoc """
`MotherboardUpdateFailedEvent` is fired when the user attempted to update
her motherboard but it failed with `reason`. Client is notified (mostly
because this is an asynchronous step).
"""

alias Helix.Server.Model.Server

Expand Down Expand Up @@ -82,6 +101,9 @@ defmodule Helix.Server.Event.Motherboard do

@event :motherboard_update_failed

@doc """
Only the player is notified (server channel with `local` access)
"""
def generate_payload(event, %{assigns: %{meta: %{access: :local}}}) do
data = %{reason: event.reason}

Expand Down
100 changes: 73 additions & 27 deletions lib/server/henforcer/component.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ defmodule Helix.Server.Henforcer.Component do
alias Helix.Entity.Henforcer.Entity, as: EntityHenforcer
alias Helix.Network.Model.Network
alias Helix.Network.Query.Network, as: NetworkQuery
alias Helix.Server.Action.Motherboard, as: MotherboardAction
alias Helix.Server.Henforcer.Server, as: ServerHenforcer
alias Helix.Server.Model.Component
alias Helix.Server.Model.Motherboard
Expand All @@ -23,6 +24,9 @@ defmodule Helix.Server.Henforcer.Component do
@spec component_exists?(Component.id) ::
{true, component_exists_relay}
| component_exists_error
@doc """
Henforces the requested component exists on the database.
"""
def component_exists?(component_id = %Component.ID{}) do
with component = %Component{} <- ComponentQuery.fetch(component_id) do
reply_ok(%{component: component})
Expand All @@ -36,11 +40,20 @@ defmodule Helix.Server.Henforcer.Component do
@type is_motherboard_relay_partial :: %{}
@type is_motherboard_error ::
{false, {:component, :not_motherboard}, is_motherboard_relay_partial}
| {false, {:motherboard, :not_attached}, is_motherboard_relay_partial}
| component_exists_error

@spec is_motherboard?(Component.t) ::
@spec is_motherboard?(Component.idt | nil) ::
{true, is_motherboard_relay}
| is_motherboard_error
@doc """
Checks whether the given component is a motherboard. `nil` is a valid input
when checking against the motherboard_id of a server.
It does not return `Motherboard.t` as a relay!
"""
def is_motherboard?(nil),
do: reply_error({:motherboard, :not_attached})
def is_motherboard?(component = %Component{type: :mobo}),
do: reply_ok(%{component: component})
def is_motherboard?(%Component{}),
Expand All @@ -58,6 +71,10 @@ defmodule Helix.Server.Henforcer.Component do
@spec can_link?(Component.mobo, Component.t, Motherboard.slot_id) ::
{true, can_link_relay}
| can_link_error
@doc """
Checks whether the given `component` can be linked to the `motherboard` at the
given `slot_id`.
"""
def can_link?(
mobo = %Component{type: :mobo},
component = %Component{},
Expand All @@ -75,9 +92,13 @@ defmodule Helix.Server.Henforcer.Component do
@type has_initial_components_error ::
{false, {:motherboard, :missing_initial_components}, %{}}

@spec has_initial_components?([term]) ::
@spec has_initial_components?([MotherboardAction.update_component]) ::
{true, has_initial_components_relay}
| has_initial_components_error
@doc """
Checks whether the given list of components, supposed to be linked to the
motherboard, matches the minimum required components (`initial_components`).
"""
def has_initial_components?(components) do
if Motherboard.has_required_initial_components?(components) do
reply_ok()
Expand All @@ -93,6 +114,10 @@ defmodule Helix.Server.Henforcer.Component do
@spec has_public_nip?([Network.Connection.t]) ::
{true, has_public_nip_relay}
| has_public_nip_error
@doc """
Checks whether, among the specified NetworkConnection changes, at least one
public NIP/NC is assigned to the motherboard.
"""
def has_public_nip?(network_connections) do
if Enum.find(network_connections, &(&1.network_id == @internet_id)) do
reply_ok()
Expand All @@ -101,22 +126,13 @@ defmodule Helix.Server.Henforcer.Component do
end
end

# TODO Merge
@typep mobo_nc ::
%{
nic_id: Component.id,
network_id: Network.id,
ip: Network.ip,
network_connection: Network.Connection.t
}

@type can_update_mobo_relay ::
%{
entity: Entity.t,
mobo: Component.mobo,
components: [term],
components: [MotherboardAction.update_component],
owned_components: [Component.t],
network_connections: [mobo_nc],
network_connections: [MotherboardAction.update_nc],
entity_network_connections: [Network.Connection.t]
}

Expand All @@ -129,9 +145,20 @@ defmodule Helix.Server.Henforcer.Component do
| EntityHenforcer.owns_component_error
| EntityHenforcer.owns_nip_error

@spec can_update_mobo?(Entity.id, Component.id, [term], [term]) ::
@spec can_update_mobo?(
Entity.id,
Component.id,
[MotherboardAction.update_component],
[MotherboardAction.update_nc])
::
{true, can_update_mobo_relay}
| can_update_mobo_error
@doc """
Checks whether `entity` can update the `mobo_id` with the given components and
network connections. It checks several underlying conditions, like if all
components exist on the DB, as well as some game mechanics stuff like whether
the mobo will have at least one public NIP assigned to it.
"""
def can_update_mobo?(entity_id, mobo_id, components, network_connections) do
reduce_components = fn mobo ->
init = {{true, %{}}, nil}
Expand Down Expand Up @@ -232,26 +259,45 @@ defmodule Helix.Server.Henforcer.Component do
end
end

@type can_detach_mobo_relay :: %{server: Server.t, motherboard: Motherboard.t}
@type can_detach_mobo_error :: component_exists_error
@type can_detach_mobo_relay ::
%{
server: Server.t,
entity: Entity.t,
mobo: Component.mobo,
motherboard: Motherboard.t,
owned_components: [Component.t]
}

@spec can_detach_mobo?(Server.idt) ::
@type can_detach_mobo_error ::
component_exists_error
| is_motherboard_error
| ServerHenforcer.server_exists_error
| EntityHenforcer.owns_component_error

@spec can_detach_mobo?(Entity.id, Server.id) ::
{true, can_detach_mobo_relay}
| can_detach_mobo_error
def can_detach_mobo?(server_id = %Server.ID{}) do
henforce ServerHenforcer.server_exists?(server_id) do
can_detach_mobo?(relay.server)
end
end

@doc """
Ensures `entity_id` can detach mobo from `server_id`.
"""
# TODO: Mainframe verification, cost analysis (for cooldown) etc. #358
def can_detach_mobo?(server = %Server{}) do
def can_detach_mobo?(entity_id, server_id) do
with \
{true, _} <- component_exists?(server.motherboard_id)
{true, r0} <- ServerHenforcer.server_exists?(server_id),
server = r0.server,

# Server must have a motherboard attached to it...
{true, _} <- is_motherboard?(server.motherboard_id),

# Entity must be the owner of that motherboard
{true, r1} <-
EntityHenforcer.owns_component?(entity_id, server.motherboard_id, nil),
r1 = replace(r1, :component, :mobo)
do
motherboard = MotherboardQuery.fetch(server.motherboard_id)
reply_ok(%{motherboard: motherboard})

reply_ok(relay([r0, r1]))
|> wrap_relay(%{motherboard: motherboard})
end
|> wrap_relay(%{server: server})
end
end
5 changes: 1 addition & 4 deletions lib/server/henforcer/server.ex
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,12 @@ defmodule Helix.Server.Henforcer.Server do
@type server_exists_error ::
{false, {:server, :not_found}, server_exists_relay_partial}

@spec server_exists?(Server.idt) ::
@spec server_exists?(Server.id) ::
{true, server_exists_relay}
| server_exists_error
@doc """
Ensures the requested server exists on the database.
"""
# TODO: REVIEW: Why does it accept `Server.t` as input?
def server_exists?(server = %Server{}),
do: server_exists?(server.server_id)
def server_exists?(server_id = %Server.ID{}) do
with server = %Server{} <- ServerQuery.fetch(server_id) do
reply_ok(%{server: server})
Expand Down
4 changes: 2 additions & 2 deletions lib/server/model/motherboard.ex
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,12 @@ defmodule Helix.Server.Model.Motherboard do
net: Component.NIC.custom
}

@type initial_components :: [{Component.pluggable, Component.Mobo.slot_id}]
@type initial_components :: [{Component.pluggable, slot_id}]
@type required_components :: [Constant.t]

@type slot_id :: Component.Mobo.slot_id
@type slot :: {slot_id, Component.t}
@type free_slots :: %{Component.type => [Component.Mobo.slot_id]}
@type free_slots :: %{Component.type => [slot_id]}

@type error ::
:wrong_slot_type
Expand Down
Loading

0 comments on commit f069b82

Please sign in to comment.