defmodule LocationSimulator do @moduledoc """ This is main api of library. To start simple call iex> LocationSimulator.start() Or start with your config iex> config = LocationSimulator.default_config() iex> config = Map.put(config, :worker, 1) iex> LocationSimulator.start(config) """ require Logger alias LocationSimulator.DynamicSupervisor, as: Sup @app_default_config Application.compile_env(:location_simulator, :default_config) @doc """ Start with config. The config is a map type. Config has info like: ``` %{ worker: 3, # number of worker will run event: 100, # number of GPS events will be trigger for a worker interval: 1000, # this & random_range used for sleep between GPS events, if value is :infinity worker will run forever (you still stop by return {:stop, reason}) random_range: 0, # 0 mean no random, other positive will be used for generate extra random sleep time callback: MyCallbackModule # your module will handle data } ``` :id is reserved for worker's id. If you need pass your data to callback module you can add that in the config. The config can be change after every event. """ @spec start(%{:worker => non_neg_integer, optional(any) => any}) :: :ok def start(config) when is_map(config) do config |> generate_worker() |> Sup.start_simulator() end @doc """ Start with default config. In this case, library just uses Logger to log data in every event. """ @spec start() :: :ok def start() do default_config() |> generate_worker() |> Sup.start_simulator() end @doc """ Get default config of library. """ @spec default_config() :: map def default_config() do Logger.debug("generating worker from config") config = @app_default_config worker = case config[:worker] do # default is one worker. nil -> 1 n when is_integer(n) and n > 0 -> n end event = case config[:event] do nil -> 1 n when is_integer(n)-> n end interval = case config[:interval] do nil -> 100 n when is_integer(n)-> n end random_range = case config[:random_range] do nil -> 10 n when is_integer(n)-> n end altitude = case config[:altitude] do nil -> 0 n when is_integer(n)-> n end altitude_way = case config[:altitude_way] do nil -> :no_up_down direction -> direction end mod = case config[:callback] do nil -> LocationSimulator.LoggerEvent m -> m end %{ worker: worker, event: event, interval: interval, random_range: random_range, direction: :random, callback: mod, altitude: altitude, altitude_way: altitude_way } end ## private functions ## @spec generate_worker(map) :: list defp generate_worker(config) do %{worker: worker} = config generate_worker(worker, config, []) end @spec generate_worker(non_neg_integer(), map, list) :: list defp generate_worker(0, _config, workers) do workers end defp generate_worker(counter, config, workers) do generate_worker(counter-1, config, [{LocationSimulator.Worker, Map.put(config, :id, counter)} | workers]) end end