diff --git a/apps/game_backend/lib/game_backend/configuration.ex b/apps/game_backend/lib/game_backend/configuration.ex index 55587b718..b7823f455 100644 --- a/apps/game_backend/lib/game_backend/configuration.ex +++ b/apps/game_backend/lib/game_backend/configuration.ex @@ -3,8 +3,10 @@ defmodule GameBackend.Configuration do Configuration context for GameBackend """ import Ecto.Query + require Decimal alias Ecto.Multi alias GameBackend.CurseOfMirra.GameConfiguration + alias GameBackend.CurseOfMirra.MapConfiguration.Position alias GameBackend.Items.ConsumableItem alias GameBackend.Units.Characters.Character alias GameBackend.CurseOfMirra.MapConfiguration @@ -534,13 +536,49 @@ defmodule GameBackend.Configuration do Repo.one(from(g in GameConfiguration, order_by: [desc: g.inserted_at], limit: 1)) end + @doc """ + Returns a 16 base encoded string representing the hashed value of the map configurations. + ## Examples + iex> get_configuration_hash_version() + "A6F0CC6917D195AB8A03129ACBE1FA48364845B8" + """ def get_configuration_hash_version do get_current_version() |> Map.get(:map_configurations) - |> Enum.flat_map(fn map_config -> Map.get(map_config, :obstacles) end) - |> Enum.flat_map(fn obstacle -> obstacle.vertices end) - |> Enum.map(fn position -> Decimal.to_string(position.x) <> Decimal.to_string(position.y) end) - |> Enum.reduce(fn position_sum_last, position_sum_current -> position_sum_current <> position_sum_last end) - |> (fn position_sum_string -> :crypto.hash(:sha, position_sum_string) |> Base.encode16() end).() + |> Enum.flat_map(fn map_config -> + Map.take(map_config, [:obstacles, :initial_positions, :bushes, :radius]) |> Map.values() + end) + |> List.flatten() + |> Enum.map(fn config -> sum_shape_coordinates(config) end) + |> Enum.reduce(fn coordinates_last, coordinates_current -> Decimal.add(coordinates_last, coordinates_current) end) + |> Decimal.to_string() + |> (fn coordinates -> :crypto.hash(:sha, coordinates) |> Base.encode16() end).() + end + + # The following function retrieves a number representing a shape's figure. + # If it's a circle, gets its radius. + # For everything else, gets its vertices' positions. + # And for everyone, gets their positions in map. + # Calculate the sum of every retrieved value. + defp sum_shape_coordinates(%Position{x: x, y: y}) do + Decimal.add(x, y) + end + + defp sum_shape_coordinates(%{shape: "circle"} = obstacle) do + Decimal.add(obstacle.radius, sum_shape_coordinates(obstacle.position)) + end + + defp sum_shape_coordinates(map_radius) when Decimal.is_decimal(map_radius) do + map_radius + end + + defp sum_shape_coordinates([]), do: Decimal.new(0) + + defp sum_shape_coordinates([vertex | vertices]) do + Decimal.add(sum_shape_coordinates(vertex), sum_shape_coordinates(vertices)) + end + + defp sum_shape_coordinates(%{position: position, vertices: vertices}) do + Decimal.add(sum_shape_coordinates(position), sum_shape_coordinates(vertices)) end end