defmodule Drone.Adapters.Sim.State do
@moduledoc false
@type t :: %__MODULE__{
x: integer(),
y: integer(),
z: integer(),
yaw: integer(),
flying: boolean(),
battery: number(),
speed: integer(),
mode: :idle | :sdk_mode | :flying | :emergency,
flight_time_seconds: non_neg_integer(),
last_command: Drone.Command.t() | nil,
command_history: [Drone.Command.t()],
config: map()
}
defstruct x: 0,
y: 0,
z: 0,
yaw: 0,
flying: false,
battery: 100,
speed: 0,
mode: :idle,
flight_time_seconds: 0,
last_command: nil,
command_history: [],
config: %{
battery_drain_per_move: 0.5,
battery_drain_per_takeoff: 2.0,
battery_drain_per_land: 1.0,
battery_drain_per_query: 0.0,
failure_rate: 0.0,
fail_commands: []
}
@spec new(keyword()) :: t()
def new(opts \\ []) do
config = %{
battery_drain_per_move: Keyword.get(opts, :battery_drain_per_move, 0.5),
battery_drain_per_takeoff: Keyword.get(opts, :battery_drain_per_takeoff, 2.0),
battery_drain_per_land: Keyword.get(opts, :battery_drain_per_land, 1.0),
battery_drain_per_query: Keyword.get(opts, :battery_drain_per_query, 0.0),
failure_rate: Keyword.get(opts, :failure_rate, 0.0),
fail_commands: Keyword.get(opts, :fail_commands, [])
}
%__MODULE__{
battery: Keyword.get(opts, :battery, 100),
config: config
}
end
@spec drain_battery(t(), float()) :: t()
def drain_battery(%__MODULE__{battery: battery} = state, amount) do
%{state | battery: max(0, battery - amount)}
end
@spec push_command(t(), Drone.Command.t()) :: t()
def push_command(%__MODULE__{command_history: history} = state, cmd) do
%{state | last_command: cmd, command_history: [cmd | history]}
end
@doc """
Increments the flight time by the given number of seconds.
Used to simulate time elapsed during command execution.
"""
@spec add_flight_time(t(), non_neg_integer()) :: t()
def add_flight_time(%__MODULE__{flight_time_seconds: t} = state, seconds) do
%{state | flight_time_seconds: t + seconds}
end
end