mirror of
https://github.com/wanderer-industries/wanderer
synced 2025-12-12 02:35:42 +00:00
Some checks failed
Build / 🚀 Deploy to test env (fly.io) (push) Has been cancelled
Build / Manual Approval (push) Has been cancelled
Build / 🛠 Build (1.17, 18.x, 27) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/amd64) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/arm64) (push) Has been cancelled
Build / merge (push) Has been cancelled
Build / 🏷 Create Release (push) Has been cancelled
163 lines
5.0 KiB
Elixir
163 lines
5.0 KiB
Elixir
defmodule WandererApp.Structure do
|
|
@moduledoc """
|
|
Encapsulates the logic for parsing and updating system structures.
|
|
"""
|
|
|
|
require Logger
|
|
alias WandererApp.Api.MapSystemStructure
|
|
alias WandererApp.Character
|
|
|
|
def update_structures(system, added, updated, removed, main_character_eve_id, user_id \\ nil) do
|
|
Logger.info("[Structure] update_structures called by user_id=#{inspect(user_id)}")
|
|
|
|
added_structs =
|
|
parse_structures(added, main_character_eve_id, system)
|
|
|> Enum.map(&Map.delete(&1, :id))
|
|
|
|
updated_structs = parse_structures(updated, main_character_eve_id, system)
|
|
removed_structs = parse_structures(removed, main_character_eve_id, system)
|
|
|
|
remove_structures(system.id, Enum.map(removed_structs, & &1.id))
|
|
update_structures_in_db(system.id, updated_structs, Enum.map(updated_structs, & &1.id))
|
|
add_structures(added_structs)
|
|
|
|
:ok
|
|
end
|
|
|
|
def search_corporation_names([], _search), do: {:ok, []}
|
|
|
|
def search_corporation_names([first_char | _], search) when is_binary(search) do
|
|
Character.search(first_char.id, params: [search: search, categories: "corporation"])
|
|
end
|
|
|
|
def search_corporation_names(_user_chars, _search), do: {:ok, []}
|
|
|
|
defp parse_structures(list_of_maps, character_eve_id, system) do
|
|
Logger.debug(fn ->
|
|
"[Structure] parse_structures =>\n" <> inspect(list_of_maps, pretty: true)
|
|
end)
|
|
|
|
Enum.map(list_of_maps, fn item ->
|
|
%{
|
|
id: Map.get(item, "id"),
|
|
system_id: system.id,
|
|
solar_system_id: system.solar_system_id,
|
|
solar_system_name: system.name,
|
|
structure_type_id: Map.get(item, "structureTypeId") || "???",
|
|
structure_type: Map.get(item, "structureType"),
|
|
character_eve_id: character_eve_id,
|
|
name: Map.get(item, "name"),
|
|
notes: Map.get(item, "notes"),
|
|
owner_name: Map.get(item, "ownerName"),
|
|
owner_ticker: Map.get(item, "ownerTicker"),
|
|
owner_id: Map.get(item, "ownerId"),
|
|
status: Map.get(item, "status"),
|
|
end_time: parse_end_time(Map.get(item, "endTime"))
|
|
}
|
|
end)
|
|
end
|
|
|
|
defp parse_end_time(str) when is_binary(str) do
|
|
Logger.debug(fn ->
|
|
"[parse_end_time] raw input => #{inspect(str)} (length=#{String.length(str)})"
|
|
end)
|
|
|
|
if String.trim(str) == "" do
|
|
nil
|
|
else
|
|
# Attempt to parse
|
|
case DateTime.from_iso8601(str) do
|
|
{:ok, dt, _offset} ->
|
|
dt
|
|
|
|
{:error, reason} ->
|
|
Logger.error(
|
|
"[parse_end_time] Invalid ISO string: #{inspect(str)}, reason: #{inspect(reason)}"
|
|
)
|
|
|
|
nil
|
|
end
|
|
end
|
|
end
|
|
|
|
defp parse_end_time(other) do
|
|
Logger.error("[parse_end_time] Received non-string => #{inspect(other)}. Returning nil.")
|
|
nil
|
|
end
|
|
|
|
defp remove_structures(system_id, removed_ids) do
|
|
MapSystemStructure.by_system_id!(system_id)
|
|
|> Enum.filter(fn s -> s.id in removed_ids end)
|
|
|> Enum.each(&Ash.destroy!/1)
|
|
end
|
|
|
|
defp update_structures_in_db(system_id, updated_structs, updated_ids) do
|
|
existing_records = MapSystemStructure.by_system_id!(system_id)
|
|
|
|
Enum.each(existing_records, fn existing ->
|
|
if existing.id in updated_ids do
|
|
updated_data = Enum.find(updated_structs, fn u -> u.id == existing.id end)
|
|
|
|
if updated_data do
|
|
Logger.debug(fn ->
|
|
"[Structure] about to update =>\n" <>
|
|
inspect(updated_data, pretty: true)
|
|
end)
|
|
|
|
# remove PK so Ash doesn't treat it as a new record
|
|
updated_data = Map.delete(updated_data, :id)
|
|
|
|
# Merge update data with existing record to avoid nil required fields
|
|
merged_data =
|
|
Map.merge(Map.from_struct(existing), updated_data, fn _k, v1, v2 ->
|
|
if is_nil(v2), do: v1, else: v2
|
|
end)
|
|
|
|
# Only keep fields accepted by Ash update action
|
|
allowed_keys = [
|
|
:system_id,
|
|
:solar_system_name,
|
|
:solar_system_id,
|
|
:structure_type_id,
|
|
:structure_type,
|
|
:character_eve_id,
|
|
:name,
|
|
:notes,
|
|
:owner_name,
|
|
:owner_ticker,
|
|
:owner_id,
|
|
:status,
|
|
:end_time
|
|
]
|
|
|
|
filtered_data = Map.take(merged_data, allowed_keys)
|
|
|
|
Logger.debug(fn ->
|
|
"[Structure] update_structures_in_db: calling update for id=#{existing.id} with: #{inspect(filtered_data)}"
|
|
end)
|
|
|
|
new_record = MapSystemStructure.update(existing, filtered_data)
|
|
|
|
Logger.debug(fn ->
|
|
"[Structure] update_structures_in_db: update result for id=#{existing.id}: #{inspect(new_record)}"
|
|
end)
|
|
|
|
Logger.debug(fn ->
|
|
"[Structure] updated record =>\n" <> inspect(new_record, pretty: true)
|
|
end)
|
|
end
|
|
end
|
|
end)
|
|
end
|
|
|
|
defp add_structures(added_structs) do
|
|
Enum.each(added_structs, fn struct_map ->
|
|
Logger.debug(fn ->
|
|
"[Structure] Creating structure =>\n" <> inspect(struct_map, pretty: true)
|
|
end)
|
|
|
|
MapSystemStructure.create!(struct_map)
|
|
end)
|
|
end
|
|
end
|