Current section
Files
Jump to
Current section
Files
lib/xplane_data_ref.ex
defmodule XPlane.DataRef do
@moduledoc """
Represent an X-Plane Data Reference (DataRef) and provide helper methods
to load the closest available set of DataRefs for a given X-Plane version
"""
@type xtype :: {:byte | :float | :int | :uint | :short | :ushort, list(integer)} | :void
defstruct [
name: "",
id: :unknown,
code: -1,
type: :void,
writable: false,
units: "???",
description: "???"]
@type t :: %XPlane.DataRef{
name: String.t,
id: atom,
code: integer,
type: XPlane.DataRef.xtype,
writable: boolean,
units: String.t,
description: String.t}
@doc """
Load the closest list of DataRefs we have available for the specified X-Plane version.
## Parameters
- version_number: X-Plane version number as returned by `XPlane.Instance.list/0`
"""
@spec load_version(integer) :: %{atom: XPlane.DataRef.t}
def load_version(version_number) do
exact = "DataRefs#{version_number}.txt.gz"
closest = "#{:code.priv_dir(:xplane)}/datarefs"
|> File.ls!
|> Enum.reverse
|> Enum.filter(&(&1 <= exact))
|> Enum.at(0)
{:ok, file} = File.open("#{:code.priv_dir(:xplane)}/datarefs/#{closest}", [:read, :compressed])
IO.stream(file, :line)
|> Enum.with_index()
|> Enum.flat_map(
fn({line, code}) ->
parse(line |> String.split("\t"), code)
end)
|> Map.new(
fn d = %XPlane.DataRef{} ->
{d.id, d}
end)
end
def describe(data_refs, pattern) do
IO.puts("\n")
data_refs
|> Enum.filter(
fn {id, _} -> Regex.match?(pattern, Atom.to_string(id)) end)
|> Enum.sort
|> Enum.map(
fn {id, %XPlane.DataRef{description: d, units: u, writable: w}} ->
wd = if w do ", writable" else "" end
"#{Atom.to_string(id) |> String.pad_trailing(40)} #{d} (#{u}#{wd})"
end)
|> Enum.join("\n")
|> IO.puts
IO.puts("\n")
end
def withCode(data_refs, code_to_match) do
[{_, matching_data_ref} | _] =
Enum.filter(data_refs,
fn {_, %XPlane.DataRef{code: code}} ->
code == code_to_match
end)
matching_data_ref
end
@spec parse(list, integer) :: list(XPlane.DataRef.t)
defp parse([name, type, writable, units, description], code) do
[%XPlane.DataRef{
parse([name, type, writable, units], code) |> Enum.at(0)
| description: binary_part(description, 0, byte_size(description) - 1)
}]
end
@spec parse(list, integer) :: list(XPlane.DataRef.t)
defp parse([name, type, writable, units], code) do
[%XPlane.DataRef{
parse([name, type, writable], code) |> Enum.at(0)
| units: units
}]
end
@spec parse(list, integer) :: list(XPlane.DataRef.t)
defp parse([name, type, writable], code) do
[%XPlane.DataRef{
name: name,
id: String.to_atom(name
|> String.slice(4..400)
|> String.replace("/", "_")),
code: code,
type: parse_type(type),
writable: (writable == "y")
}]
end
defp parse(_, _) do
[]
end
@spec parse_type(String.t) :: XPlane.DataRef.xtype
defp parse_type(type) do
[type | dims] = type |> String.split(["[", "]"], trim: true)
{String.to_atom(type), if Enum.empty?(dims) do [1] else dims |> Enum.map(&(String.to_integer(&1))) end}
end
end