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

Commit

Permalink
Merge 9bd7b5a into 0e092d7
Browse files Browse the repository at this point in the history
  • Loading branch information
renatomassaro committed Nov 17, 2017
2 parents 0e092d7 + 9bd7b5a commit bd3cc16
Show file tree
Hide file tree
Showing 22 changed files with 1,591 additions and 1 deletion.
22 changes: 22 additions & 0 deletions lib/hell/hell/ecto_macros.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
defmodule HELL.Ecto.Macros do

@doc """
Syntactic-sugar for our way-too-common Query module
"""
defmacro query(do: block) do
quote do

defmodule Query do
@moduledoc false

import Ecto.Query

alias Ecto.Queryable
alias unquote(__CALLER__.module)

unquote(block)
end

end
end
end
16 changes: 16 additions & 0 deletions lib/hell/hell/macros_utils.ex
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,22 @@ defmodule HELL.Macros.Utils do
|> Module.concat()
end

def atomize_module_name({_a, _s, [t]}),
do: atomize_module_name(t)
def atomize_module_name(module) when is_atom(module) do
module
|> Atom.to_string()
|> String.downcase()
|> String.to_atom()
end

def get_parent_module(module) do
module
|> Module.split()
|> Enum.drop(-1)
|> Module.concat()
end

docp """
Small workaround for greater flexibility of `remove_protocol_namespace/2`.
In some cases, the removal may happen at the protocol's flow instead of the
Expand Down
16 changes: 16 additions & 0 deletions lib/hell/hell/utils.ex
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,20 @@ defmodule HELL.Utils do
def concat_atom(a, b) when is_binary(a) and is_binary(b),
do: String.to_atom(a <> b)

def upcase_atom(a) when is_atom(a) do
a
|> Atom.to_string()
|> String.upcase()
|> String.to_atom()
end

def downcase_atom(a) when is_atom(a) do
a
|> Atom.to_string()
|> String.downcase()
|> String.to_atom()
end

@spec concat(atom | String.t, atom | String.t) ::
String.t
@doc """
Expand Down Expand Up @@ -79,4 +93,6 @@ defmodule HELL.Utils do
do: nil
def stringify(value),
do: to_string(value)

# TODO: Make Atom.upcase & Atom.downcase
end
46 changes: 46 additions & 0 deletions lib/server/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Hardware

## Tentative API

### Motherboard

#### Action



#### Query

- get_resources(mobo_id) :: %{cpu: %{clock: x}, hdd: %{size: y, iops: z}}


### Component

#### Action

#### Query

- fetch(comp_id)

- fetch_spec(spec_id)

### Comments

- components are global (can be used by any mobo)
- mobos are specific per type of server
- they (mobo) define most custom behaviour
- components may receive server_type to further customize behaviour

o Mainframe

- main PC. must always be online. Must not be disassembled/taken offline

o Durability

- affects effective power for each resource (percentage multiplier *per component*)
- consumption based on TOP's processed info (updated on ProcessCompletedEvent)

o Orphaned components

- orphaned components must be linked to their entity
- effective power of the component must be persisted alongside it

100 changes: 100 additions & 0 deletions lib/server/component/componentable.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
defmodule Helix.Server.Componentable do

use Helix.Server.Component.Flow

component CPU do

defstruct [:clock]

def new(cpu = %{type: :cpu}) do
%CPU{
clock: cpu.clock
}
end

resource :clock
end

component HDD do

defstruct [:size, :iops]

def new(hdd = %{type: :hdd}) do
%HDD{
size: hdd.size,
iops: hdd.iops
}
end

resource :size
resource :iops
end

component MOBO do

defstruct []

def new(_mobo = %{type: :mobo}) do
%MOBO{}
end

custom do

alias Helix.Server.Component.Specable

def check_compatibility(
mobo_spec_id,
component_spec_id,
slot_id,
used_slots)
do
mobo_spec = Specable.fetch(mobo_spec_id)
component_spec = Specable.fetch(component_spec_id)

{tentative_slot, real_id} = split_slot_id(slot_id)

all_slots_ids =
mobo_spec.slots
|> Map.fetch!(component_spec.component_type)
|> Map.keys()

with \
true <-
valid_slot?(component_spec.component_type, tentative_slot)
|| {:error, :wrong_slot_type},
# /\ The component is being linked to the correct slot type

# The mobo has that requested slot
true <- real_id in all_slots_ids || {:error, :bad_slot},

# The requested slot is not being used by any other component
true <-
not Enum.any?(used_slots, fn {used_id, _} -> used_id == slot_id end)
|| {:error, :slot_in_use}
do
:ok
end
end

def valid_slot?(:cpu, tentative),
do: tentative in [:cpu]
def valid_slot?(:hdd, tentative),
do: tentative in [:hdd, :sata, :nvme]
def valid_slot?(:ram, tentative),
do: tentative in [:ram]
def valid_slot?(:nic, tentative),
do: tentative in [:nic]

def split_slot_id(slot_id) when is_atom(slot_id),
do: split_slot_id(Atom.to_string(slot_id))
def split_slot_id("cpu_" <> id),
do: {:cpu, id |> String.to_integer()}
def split_slot_id("hdd_" <> id),
do: {:hdd, id |> String.to_integer()}
def split_slot_id("ram_" <> id),
do: {:ram, id |> String.to_integer()}
def split_slot_id("nic_" <> id),
do: {:nic, id |> String.to_integer()}
end
end
end
110 changes: 110 additions & 0 deletions lib/server/component/flow.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
defmodule Helix.Server.Component.Flow do

import HELL.Macros.Utils

alias HELL.Utils

defmacro __using__(_) do
quote location: :keep do

import unquote(__MODULE__)

Module.register_attribute(__MODULE__, :components, accumulate: true)

@before_compile unquote(__MODULE__)
end
end

defmacro __before_compile__(_) do
quote location: :keep do

unquote(components_functions())

end
end

defp components_functions do
quote do

def get_resources(component) do
dispatch(component.type, :new, [component])
end

def dispatch(type, fun, args) do
component_module = get_module_name(type)

module =
__MODULE__
|> Utils.concat_atom(".")
|> Utils.concat_atom(component_module)

apply(module, fun, args)
end

defp get_module_name(type) do
type
|> Atom.to_string()
|> String.upcase()
|> String.to_atom()
end
end
end

defmacro component(name, do: block) do
comp_name = atomize_module_name(name)

quote do

Module.put_attribute(
unquote(__CALLER__.module),
:components,
unquote(comp_name)
)

defmodule unquote(name) do

unquote(block)
end

end
end

defmacro custom(do: block) do
quote do

module_name =
__MODULE__
|> Module.split()
|> Enum.take(-1)
|> List.first()
|> String.downcase()
|> String.to_atom()
|> case do
:mobo ->
Helix.Server.Model.Component.Mobo

elem ->
Utils.concat_atom(
Helix.Server.Model.Component, Utils.upcase_atom(elem)
)
end

defmodule module_name do

unquote(block)
end
end
end

# Default behaviour is to get the given resource field directly. For custom
# implementation, use `resource/2`
defmacro resource(name) when is_atom(name) do
quote do

def unquote(:"get_#{name}")(component) do
Map.fetch!(component, unquote(name))
end

end
end
end
Loading

0 comments on commit bd3cc16

Please sign in to comment.