defmodule BoosterTutor.BoosterGenerator do require Logger @type retail_booster_types :: :play | :collector def string_to_booster_type!(param) do case param do "play" -> :play "collector" -> :collector _ -> raise("Invalid booster type given #{param}") end end @spec generate_booster_for_set(String, String) :: nil def generate_booster_for_set(set_code, booster_type) do booster_type = string_to_booster_type!(booster_type) generate_retail_booster_for_set(set_code, booster_type) end @spec generate_retail_booster_for_set(String, retail_booster_types()) :: :ok def generate_retail_booster_for_set(set_code, booster_type) do case booster_type do :play -> generate_play_booster_for_set(set_code) :collector -> raise("Not implemented collector boosters yet") end end @spec generate_play_booster_for_set(String) :: map() def generate_play_booster_for_set(set_code) do set_json = load_set_file(set_code) selected_config = select_booster_config(set_json["booster"]["play"]["boosters"]) sheets = set_json["booster"]["play"]["sheets"] pulls = Enum.reduce(selected_config["contents"], fn({sheet, quantity}, acc) -> IO.inspect(sheet, label: "sheet") IO.inspect(quantity, label: "quantity") selected_sheet = sheets[sheet] IO.inspect(selected_sheet, label: "selected_sheet") picks = pick_n_from_sheet(selected_sheet, quantity) IO.inspect(picks, label: "picks") Map.put(acc, sheet, picks) end) %{message: "OK", pulls: pulls} end @spec select_booster_config(list(map())) :: map() def select_booster_config(booster_configs) do duplicated_configs = Enum.map(booster_configs, fn config -> weight = config["weight"] List.duplicate(config, weight) end) |> List.flatten() final_config = List.first(Enum.take_random(duplicated_configs, 1)) Logger.info("Selected a random booster config. #{inspect(final_config, pretty: true)}") final_config end @spec pick_n_from_sheet(map(), integer()) :: list(any()) def pick_n_from_sheet(sheet, quantity) do # Build our weighted random thingy. cards = sheet["cards"] weights = cards |> Enum.map(fn {id, weight} -> {id, weight} end) pulls = WeightedRandom.take_n(weights, quantity) pulls end def load_set_file(set_code) do project_root = Application.fetch_env!(:booster_tutor, :project_root) path = "#{project_root}/priv/card_data/#{set_code}.json" {:ok, body} = File.read(path) {:ok, json} = Jason.decode(body) json end end