diff --git a/src/zenflows/vf/economic_event/domain.ex b/src/zenflows/vf/economic_event/domain.ex index 40e588a..c6badca 100644 --- a/src/zenflows/vf/economic_event/domain.ex +++ b/src/zenflows/vf/economic_event/domain.ex @@ -71,6 +71,35 @@ def previous(id) do end end +@spec trace_dpp_before(EconomicEvent.t(), non_neg_integer(), + MapSet.t(), [EconomicResource.t() | EconomicEvent.t() | Process.t()]) + :: {MapSet.t(), [EconomicResource.t() | EconomicEvent.t() | Process.t()]} +def trace_dpp_before(_, 0, visited, children), do: {visited, children} +def trace_dpp_before(evt, depth, visited, children) do + {:ok, result} = Repo.multi(fn -> + children = [evt | children] + case previous(evt) do + nil -> + {:ok, {visited, children}} + %EconomicEvent{} = evt -> + if MapSet.member?(visited, "evt#{evt.id}"), + do: {:ok, {visited, children}}, + else: {:ok, trace_dpp_before(evt, depth - 1, visited, children)} + %EconomicResource{} = res -> + if MapSet.member?(visited, "res#{res.id}"), + do: {:ok, {visited, children}}, + else: {:ok, + EconomicResource.Domain.trace_dpp_before(res, depth - 1, visited, children)} + %Process{} = proc -> + if MapSet.member?(visited, "prc#{proc.id}"), + do: {:ok, {visited, children}}, + else: {:ok, + Process.Domain.trace_dpp_before(proc, depth - 1, visited, children)} + end + end) + result +end + @spec create(Schema.params(), nil | Schema.params()) :: {:ok, EconomicEvent.t()} | {:error, String.t() | Changeset.t()} def create(evt_params, res_params \\ nil) do diff --git a/src/zenflows/vf/economic_resource/domain.ex b/src/zenflows/vf/economic_resource/domain.ex index 8e0fb9d..f0c3a61 100644 --- a/src/zenflows/vf/economic_resource/domain.ex +++ b/src/zenflows/vf/economic_resource/domain.ex @@ -183,6 +183,42 @@ end defp handle_set(_, _, flows, visited, contained, modified, delivered, saved_event), do: {flows, visited, contained, modified, delivered, saved_event} +@spec trace_dpp(EconomicResource.t()) :: [EconomicResource.t() | EconomicEvent.t() | Process.t()] +def trace_dpp(res) do + {:ok, result} = Repo.multi(fn -> + # the initial value for `_depth_countdown` was taken from: + # https://github.com/interfacerproject/Interfacer-notebook/blob/326750b1cae445ce5faa0fafb057e50538077910/if_consts.py#L25 + {_visited, children} = + trace_dpp_before(res, _depth_countdown = 100_000_000, _visited = MapSet.new(), _children = []) + {:ok, children} + end) + result +end + +@spec trace_dpp_before(EconomicResource.t(), non_neg_integer(), + MapSet.t(), [EconomicResource.t() | EconomicEvent.t() | Process.t()]) + :: {MapSet.t(), [EconomicResource.t() | EconomicEvent.t() | Process.t()]} +def trace_dpp_before(_, 0, visited, children), do: {visited, children} +def trace_dpp_before(res, depth, visited, children) do + {:ok, result} = Repo.multi(fn -> + children = [res | children] + {visited, not_visited} = + previous(res) + |> Enum.reduce({visited, []}, fn evt, {visited, not_visited} -> + if MapSet.member?(visited, "evt#{evt.id}"), + do: {visited, not_visited}, + else: {MapSet.put(visited, "evt#{evt.id}"), [evt | not_visited]} + end) + {:ok, + not_visited + |> Enum.reverse() + |> Enum.reduce({visited, children}, fn evt, {visited, children} -> + EconomicEvent.Domain.trace_dpp_before(evt, depth - 1, visited, children) + end)} + end) + result +end + @spec classifications(Page.t()) :: {:ok, [String.t()]} | {:error, Changeset.t()} def classifications(page \\ Page.new()) do with {:ok, q} <- Query.classifications(page) do @@ -271,87 +307,4 @@ def multi_delete(m, key \\ multi_key(), id) do |> multi_one("#{key}.one", id) |> Multi.delete(key, &Map.fetch!(&1, "#{key}.one")) end - -@max_depth 100_000_000 - -@spec trace_dpp_er_before(EconomicResource.t(), MapSet.t(), integer()) :: {MapSet.t(), map()} -def trace_dpp_er_before(_item, visited, depth) when depth >= @max_depth do - {visited, %{}} -end -def trace_dpp_er_before(%EconomicResource{} = item, visited, depth) do - a_dpp_item = %{type: "EconomicResource", node: item} - {visited2, children} = EconomicResource.Domain.previous(item) |> Enum.reduce({visited, []}, - fn ee, {visited, children} -> - if MapSet.member?(visited, {ee.__struct__, ee.id}) do - {visited, children} - else - {visited2, child} = trace_dpp_ee_before(ee, MapSet.put(visited, {ee.__struct__, ee.id}), depth + 1) - {visited2, [child | children]} - end - end - ) - {visited2, Map.put(a_dpp_item, :children, children)} -end - -@spec trace_dpp_ee_before_recurse( - EconomicEvent.t() | EconomicResource.t() | Process.t(), - MapSet.t(), pos_integer() ) :: {MapSet.t(), map()} -def trace_dpp_ee_before_recurse(%EconomicResource{} = item, visited, depth) do - trace_dpp_er_before(item, visited, depth) -end -def trace_dpp_ee_before_recurse(%EconomicEvent{} = item, visited, depth) do - trace_dpp_ee_before(item, MapSet.put(visited, {item.__struct__, item.id}), depth) -end -def trace_dpp_ee_before_recurse(%Process{} = item, visited, depth) do - trace_dpp_pr_before(item, MapSet.put(visited, {item.__struct__, item.id}), depth) -end - -@spec trace_dpp_ee_before(EconomicEvent.t(), MapSet.t(), pos_integer()) :: {MapSet.t(), map()} -def trace_dpp_ee_before(_item, visited, depth) when depth >= @max_depth do - {visited, %{}} -end -def trace_dpp_ee_before(%EconomicEvent{} = item, visited, depth) do - a_dpp_item = %{type: "EconomicEvent", node: item} - pr_item = EconomicEvent.Domain.previous(item) - if pr_item == nil do - {visited, Map.put(a_dpp_item, :children, [])} - else - {visited2, children} = [pr_item] |> Enum.reduce({visited, []}, - fn pf, {visited, children} -> - if MapSet.member?(visited, {pf.__struct__, pf.id}) do - {visited, children} - else - {visited2, child} = trace_dpp_ee_before_recurse(pf, visited, depth + 1) - {visited2, [child | children]} - end - end - ) - {visited2, Map.put(a_dpp_item, :children, children)} - end -end - -@spec trace_dpp_pr_before(Process.t(), MapSet.t(), integer()) :: {MapSet.t(), map()} -def trace_dpp_pr_before(_item, visited, depth) when depth >= @max_depth do - {visited, %{}} -end -def trace_dpp_pr_before(item, visited, depth) do - a_dpp_item = %{type: "Process", node: item} - {visited2, children} = Process.Domain.previous(item) |> Enum.reduce({visited, []}, - fn ee, {visited, children} -> - if MapSet.member?(visited, {ee.__struct__, ee.id}) do - {visited, children} - else - {visited2, child} = trace_dpp_ee_before(ee, MapSet.put(visited, {ee.__struct__, ee.id}), depth + 1) - {visited2, [child | children]} - end - end - ) - {visited2, Map.put(a_dpp_item, :children, children)} -end - -@spec trace_dpp(EconomicResource.t(), Page.t()) :: map() -def trace_dpp(item, _page \\ Page.new()) do - {_, dpp} = trace_dpp_er_before(item, MapSet.new(), 0) - dpp -end end diff --git a/src/zenflows/vf/economic_resource/type.ex b/src/zenflows/vf/economic_resource/type.ex index 2872ed1..786d502 100644 --- a/src/zenflows/vf/economic_resource/type.ex +++ b/src/zenflows/vf/economic_resource/type.ex @@ -186,7 +186,7 @@ object :economic_resource do field :trace, list_of(non_null(:track_trace_item)), resolve: &Resolv.trace/3 - field :trace_dpp, non_null(:json), resolve: &Resolv.trace_dpp/3 + field :trace_dpp, non_null(:json_array), resolve: &Resolv.trace_dpp/3 end input_object :economic_resource_create_params do diff --git a/src/zenflows/vf/process/domain.ex b/src/zenflows/vf/process/domain.ex index 0f2fd5d..3fb0006 100644 --- a/src/zenflows/vf/process/domain.ex +++ b/src/zenflows/vf/process/domain.ex @@ -25,6 +25,7 @@ alias Ecto.Changeset alias Zenflows.DB.{Page, Repo, Schema} alias Zenflows.VF.{ EconomicEvent, + EconomicResource, Process, Process.Query, ProcessGroup, @@ -71,6 +72,24 @@ def previous(id, page) do |> Enum.reverse() end +@spec trace_dpp_before(Process.t(), non_neg_integer(), + MapSet.t(), [EconomicResource.t() | EconomicEvent.t() | Process.t()]) + :: {MapSet.t(), [EconomicResource.t() | EconomicEvent.t() | Process.t()]} +def trace_dpp_before(_, 0, visited, children), do: {visited, children} +def trace_dpp_before(proc, depth, visited, children) do + {:ok, result} = Repo.multi(fn -> + children = [proc | children] + previous(proc) + |> Enum.reduce({visited, children}, fn evt, {visited, children} -> + if MapSet.member?(visited, "evt#{evt.id}"), + do: {visited, children}, + else: EconomicEvent.Domain.trace_dpp_before(evt, depth - 1, + MapSet.put(visited, "evt#{evt.id}"), children) + end) + end) + result +end + @spec create(Schema.params()) :: {:ok, Process.t()} | {:error, Changeset.t()} def create(params) do Repo.multi(fn ->