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

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
renatomassaro committed Feb 16, 2018
1 parent ce072c4 commit 640f243
Show file tree
Hide file tree
Showing 14 changed files with 332 additions and 13 deletions.
2 changes: 2 additions & 0 deletions lib/event/dispatcher.ex
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ defmodule Helix.Event.Dispatcher do
event SoftwareEvent.LogForge.LogCreate.Processed
event SoftwareEvent.LogForge.LogEdit.Processed
event SoftwareEvent.Virus.Collect.Processed
event SoftwareEvent.Virus.Collected
event SoftwareEvent.Virus.Installed
event SoftwareEvent.Virus.InstallFailed

Expand Down Expand Up @@ -262,6 +263,7 @@ defmodule Helix.Event.Dispatcher do

# All
event BankEvent.Bank.Account.Login
event BankEvent.Bank.Account.Updated
event BankEvent.Bank.Account.Password.Revealed
event BankEvent.Bank.Account.Token.Acquired
event BankEvent.Bank.Transfer.Processed
Expand Down
43 changes: 43 additions & 0 deletions lib/software/action/virus.ex
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
defmodule Helix.Software.Action.Virus do

alias Helix.Event
alias Helix.Entity.Model.Entity
alias Helix.Universe.Bank.Action.Bank, as: BankAction
alias Helix.Universe.Bank.Model.BankAccount
alias Helix.Software.Internal.Virus, as: VirusInternal
alias Helix.Software.Model.File
alias Helix.Software.Model.Virus
alias Helix.Software.Query.Virus, as: VirusQuery

alias Helix.Software.Event.Virus.Collected, as: VirusCollectedEvent
alias Helix.Software.Event.Virus.Installed, as: VirusInstalledEvent
alias Helix.Software.Event.Virus.InstallFailed, as: VirusInstallFailedEvent

Expand All @@ -24,4 +29,42 @@ defmodule Helix.Software.Action.Virus do
{:error, reason, [event]}
end
end

@spec collect(File.t, Virus.payment_info) ::
{:ok, [Event.t]}
| {:error, [Event.t]}
@doc """
Collects the earnings of the virus (identified by `file`) and transfers them
to the address in `payment_info`.
"""
def collect(file, payment_info) do
virus = VirusQuery.fetch(file.file_id)

with \
earnings = Virus.calculate_earnings(file, virus, []),
true <- is_integer(earnings),
{:ok, _, payment_events} <-
collect_payment(file.software_type, earnings, payment_info),
{:ok, _} <- VirusInternal.zero_running_time(virus)
do
event = VirusCollectedEvent.new(virus, earnings, payment_info)

{:ok, [event | payment_events]}
else
_ ->
# reason = :todo
# event = VirusCollectFailedEvent.new(virus, reason)
event = []

{:error, [event]}
end

end

@spec collect_payment(
:virus_spyware, BankAccount.amount, {BankAccount.t, term})
::
{:ok, BankAccount.t, [BankAccountUpdatedEvent.t]}
defp collect_payment(:virus_spyware, amount, {account = %BankAccount{}, _}),
do: BankAction.direct_deposit(account, amount)
end
7 changes: 6 additions & 1 deletion lib/software/event/handler/virus.ex
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
defmodule Helix.Software.Event.Handler.Virus do

alias Helix.Event

alias Helix.Software.Action.Virus, as: VirusAction

alias Helix.Software.Event.File.Install.Processed,
as: FileInstallProcessedEvent
alias Helix.Software.Event.Virus.Collect.Processed,
as: VirusCollectProcessedEvent

@doc """
Handles the completion of FileInstallProcess when the target file is a virus.
Expand All @@ -29,4 +30,8 @@ defmodule Helix.Software.Event.Handler.Virus do
end
def virus_installed(%FileInstallProcessedEvent{backend: _}),
do: :noop

def handle_collect(%VirusCollectProcessedEvent{}) do
IO.puts "collected"
end
end
59 changes: 59 additions & 0 deletions lib/software/event/virus.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,65 @@ defmodule Helix.Software.Event.Virus do

import Helix.Event

event Collected do
@moduledoc """
`VirusCollectedEvent` is fired right after the earnings of the virus have
been collected and transferred to the player's bank account/bitcoin wallet.
"""

alias Helix.Software.Model.Virus

event_struct [:virus, :earnings, :payment_info]

@type t ::
%__MODULE__{
virus: Virus.t,
earnings: Virus.earnings,
payment_info: Virus.payment_info
}

@spec new(Virus.t, Virus.earnings, Virus.payment_info) ::
t
def new(virus = %Virus{}, earnings, payment_info = {_, _}) do
%__MODULE__{
virus: virus,
earnings: earnings,
payment_info: payment_info
}
end

notify do
@moduledoc """
Notifying that a virus has been collected enables the client to reset the
running time of the virus.
"""

alias Helix.Universe.Bank.Model.BankAccount

@event :virus_collected_event

def generate_payload(event = %{}, _socket) do
data =
event
|> payment_data()
|> Map.merge(%{file_id: to_string(event.virus.file_id)})

{:ok, data}
end

defp payment_data(event = %{payment_info: {acc = %BankAccount{}, _}}) do
%{
atm_id: to_string(acc.atm_id),
account_number: acc.account_number,
money: event.earnings
}
end

def whom_to_notify(event),
do: %{account: event.virus.entity_id}
end
end

event Installed do
@moduledoc """
`VirusInstalledEvent` is fired when a virus has been installed by someone.
Expand Down
27 changes: 27 additions & 0 deletions lib/software/internal/virus.ex
Original file line number Diff line number Diff line change
Expand Up @@ -130,12 +130,30 @@ defmodule Helix.Software.Internal.Virus do
def activate_virus(virus = %Virus{}, storage_id = %Storage.ID{}) do
result = force_activate_virus(virus, storage_id)

# Review: really? because comment says only `:nothing`
# See `install/2` comments on why we have to fetch again.
with {:ok, _} <- result do
{:ok, fetch(virus.file_id)}
end
end

@spec zero_running_time(Virus.t) ::
{:ok, Virus.t}
| {:error, :internal}
@doc """
Zeroes the running time of a virus (by resetting its `Virus.Active` activation
time)
"""
def zero_running_time(virus = %Virus{}) do
case reset_activation_time(virus) do
{1, _} ->
{:ok, fetch(virus.file_id)}

_ ->
{:error, :internal}
end
end

@spec insert_virus(File.t, Entity.id) ::
{:ok, Virus.t}
| {:error, Virus.changeset}
Expand Down Expand Up @@ -167,4 +185,13 @@ defmodule Helix.Software.Internal.Virus do
on_conflict: :replace_all, conflict_target: [:entity_id, :storage_id]
)
end

@spec reset_activation_time(Virus.t) ::
{integer, nil}
| :no_return
defp reset_activation_time(virus = %Virus{}) do
virus.file_id
|> Virus.Active.Query.by_virus()
|> Repo.update_all(set: [activation_time: DateTime.utc_now()])
end
end
9 changes: 9 additions & 0 deletions lib/software/model/virus.ex
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ defmodule Helix.Software.Model.Virus do
| {nil, wallet}
| {BankAccount.t, nil}

@type earnings :: BankAccount.amount | float

@type changeset :: %Changeset{data: %__MODULE__{}}
@type id :: File.id

Expand Down Expand Up @@ -99,6 +101,13 @@ defmodule Helix.Software.Model.Virus do
active: nil}
end

def calculate_earnings(
_file = %File{}, _virus = %Virus{is_active?: true}, _saved_earnings)
do
# Obviously TODO
5000
end

query do

alias Helix.Entity.Model.Entity
Expand Down
27 changes: 25 additions & 2 deletions lib/universe/bank/action/bank.ex
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ defmodule Helix.Universe.Bank.Action.Bank do
alias Helix.Universe.Bank.Query.Bank, as: BankQuery

alias Helix.Network.Event.Connection.Closed, as: ConnectionClosedEvent
alias Helix.Universe.Bank.Event.Bank.Account.Login,
as: BankAccountLoginEvent
alias Helix.Universe.Bank.Event.Bank.Account.Login, as: BankAccountLoginEvent
alias Helix.Universe.Bank.Event.Bank.Account.Updated,
as: BankAccountUpdatedEvent
alias Helix.Universe.Bank.Event.Bank.Account.Password.Revealed,
as: BankAccountPasswordRevealedEvent
alias Helix.Universe.Bank.Event.Bank.Account.Token.Acquired,
Expand Down Expand Up @@ -117,6 +118,28 @@ defmodule Helix.Universe.Bank.Action.Bank do
to: BankAccountInternal,
as: :close

@spec direct_deposit(BankAccount.t, BankAccount.amount) ::
{:ok, BankAccount.t, [BankAccountUpdatedEvent.t]}
| {:error, :internal}
@doc """
Performs a direct deposit of $`amount` into `account`.
NOTE: This is a direct deposit, and is meant for internal mechanics only, like
when the player collects money off of viruses, or when rewards of a mission
should be sent to the player. Not to confuse with direct financial mechanics,
like transferring moneys between player accounts, in which case the underlying
`BankTransferProcess` should be used instead.
"""
def direct_deposit(account, amount) do
case BankAccountInternal.deposit(account, amount) do
{:ok, account} ->
{:ok, account, [BankAccountUpdatedEvent.new(account, :balance)]}

error ->
error
end
end

@spec generate_token(BankAccount.t, Connection.idt, Entity.idt) ::
{:ok, BankToken.t, [BankAccountTokenAcquiredEvent.t]}
| {:error, Ecto.Changeset.t}
Expand Down
60 changes: 58 additions & 2 deletions lib/universe/bank/event/bank/account.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,76 @@ defmodule Helix.Universe.Bank.Event.Bank.Account do

import Helix.Event

event Updated do
@moduledoc """
`BankAccountUpdatedEvent` is fired when the underlying bank account has
changed. It may happen either due to a balance update (most commonly) or due
to a password change.
"""

alias Helix.Universe.Bank.Model.BankAccount

event_struct [:account, :reason]

@type t ::
%__MODULE__{
account: BankAccount.t,
reason: reason
}

@type reason :: :balance | :password

@spec new(BankAccount.t, reason) ::
t
def new(account = %BankAccount{}, reason) do
%__MODULE__{
account: account,
reason: reason
}
end

notify do
@moduledoc """
Notifies the client of the bank account update, so it can properly update
the local data
"""

@event :bank_account_updated

@doc false
def generate_payload(event, _socket) do
data =
%{
atm_id: to_string(event.account.atm_id),
account_number: to_string(event.account.account_number),
balance: event.account.balance,
password: event.account.password,
reason: to_string(event.reason)
}

{:ok, data}
end

@doc false
def whom_to_notify(event),
do: %{account: event.account.owner_id}
end
end

event Login do

alias Helix.Entity.Model.Entity
alias Helix.Universe.Bank.Model.BankAccount
alias Helix.Universe.Bank.Model.BankToken

event_struct [:entity_id, :account, :token_id]

@type t :: %__MODULE__{
entity_id: Entity.id,
account: BankAccount.t,
token_id: BankToken.id | nil
}

event_struct [:entity_id, :account, :token_id]

@spec new(BankAccount.t, Entity.id) ::
t
def new(account = %BankAccount{}, entity_id, token_id \\ nil) do
Expand Down
5 changes: 4 additions & 1 deletion lib/universe/bank/model/bank_account.ex
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,13 @@ defmodule Helix.Universe.Bank.Model.BankAccount do
bank_id: NPC.id,
atm_id: ATM.id,
password: String.t,
balance: non_neg_integer,
balance: balance,
owner_id: Account.id
}

@type balance :: non_neg_integer
@type amount :: pos_integer

@type creation_params :: %{
bank_id: NPC.idtb,
atm_id: ATM.idtb,
Expand Down
Loading

0 comments on commit 640f243

Please sign in to comment.