Skip to content

Instantly share code, notes, and snippets.

@houmanka
Last active April 12, 2019 08:42
Show Gist options
  • Save houmanka/0dad39b1317f79022a9fda8f15363bd1 to your computer and use it in GitHub Desktop.
Save houmanka/0dad39b1317f79022a9fda8f15363bd1 to your computer and use it in GitHub Desktop.
[
%{
finish: ~D[2019-04-08],
user: %{first_name: "Josh", hours: 1.0, id: 24, last_name: "Proud"}
},
%{
finish: ~D[2019-04-09],
user: %{first_name: "Josh", hours: 1.0, id: 24, last_name: "Proud"}
},
%{
finish: ~D[2019-04-09],
user: %{first_name: "Jane", hours: 1.0, id: 29, last_name: "Smith"}
},
%{
finish: ~D[2019-04-14],
user: %{first_name: "Josh", hours: 25.0, id: 24, last_name: "Proud"}
},
%{
finish: ~D[2019-04-20],
user: %{first_name: "Josh", hours: 1.0, id: 24, last_name: "Proud"}
},
%{
finish: ~D[2019-05-06],
user: %{first_name: "Houman", hours: 1.0, id: 29, last_name: "Kargaran"}
},
%{
finish: ~D[2019-06-12],
user: %{first_name: "Houman", hours: 1.0, id: 29, last_name: "Kargaran"}
}
]
[%{
"2019-04-05": nil,
"2019-04-12": [%{first_name: "Josh", hours: 2.0, id: 24, last_name: "Proud"},
%{first_name: "Jane", hours: 1.0, id: 29, last_name: "Smith"}],
"2019-04-19": [%{first_name: "Josh", hours: 25.0, id: 24, last_name: "Proud"}],
"2019-04-26": [%{first_name: "Josh", hours: 1.0, id: 24, last_name: "Proud"}],
"2019-05-03": nil,
"2019-05-10": [%{first_name: "Houman", hours: 1.0, id: 29, last_name: "Kargaran"}],
"2019-05-17": nil,
"2019-05-24": nil,
"2019-05-31": nil,
"2019-06-07": nil,
"2019-06-14": [%{first_name: "Houman", hours: 1.0, id: 29, last_name: "Kargaran"}],
"2019-06-21": nil,
"2019-06-28": nil }]
[~D[2019-04-05], ~D[2019-04-12], ~D[2019-04-19], ~D[2019-04-26], ~D[2019-05-03],
~D[2019-05-10], ~D[2019-05-17], ~D[2019-05-24], ~D[2019-05-31], ~D[2019-06-07],
~D[2019-06-14], ~D[2019-06-21], ~D[2019-06-28]]
Copy link

ghost commented Apr 12, 2019

Might be not the most prettiest approach, but:

defmodule Grouping do
  @spec group([Date.t()], [map]) :: [map]
  def group([start | _rest] = weekends, records) do
    [do_group(weekends, records, Map.put(%{}, Date.to_string(start), nil))]
  end

  defp do_group([start | [stop | inner_rest] = outer_rest], records, acc) do
    acc =
      records
      |> Enum.filter(fn %{finish: finish} ->
        Date.compare(start, finish) in [:lt, :eq] and Date.compare(stop, finish) in [:gt]
      end)
      |> Enum.map(fn %{user: user} -> user end)
      |> Enum.reduce([], fn user, users -> add_hours(users, user) end)
      |> case do
        [] -> Map.put(acc, Date.to_string(stop), nil)
        users when is_list(users) -> Map.put(acc, Date.to_string(stop), users)
      end

    case inner_rest do
      [] -> acc
      _other -> do_group(outer_rest, records, acc)
    end
  end

  defp add_hours(users, %{id: new_user_id, hours: new_hours} = new_user) do
    if Enum.find(users, fn %{id: user_id} -> user_id == new_user_id end) do
      Enum.map(users, fn %{id: ^new_user_id, hours: old_hours} = old_user ->
        %{old_user | hours: old_hours + new_hours}
      end)
    else
      [new_user | users]
    end
  end
end
defmodule GroupingTest do
  use ExUnit.Case

  test "it works" do
    events = [
      %{
        finish: ~D[2019-04-08],
        user: %{first_name: "Josh", hours: 1.0, id: 24, last_name: "Proud"}
      },
      %{
        finish: ~D[2019-04-09],
        user: %{first_name: "Josh", hours: 1.0, id: 24, last_name: "Proud"}
      },
      %{
        finish: ~D[2019-04-09],
        user: %{first_name: "Jane", hours: 1.0, id: 29, last_name: "Smith"}
      },
      %{
        finish: ~D[2019-04-14],
        user: %{first_name: "Josh", hours: 25.0, id: 24, last_name: "Proud"}
      },
      %{
        finish: ~D[2019-04-20],
        user: %{first_name: "Josh", hours: 1.0, id: 24, last_name: "Proud"}
      },
      %{
        finish: ~D[2019-05-06],
        user: %{first_name: "Houman", hours: 1.0, id: 29, last_name: "Kargaran"}
      },
      %{
        finish: ~D[2019-06-12],
        user: %{first_name: "Houman", hours: 1.0, id: 29, last_name: "Kargaran"}
      }
    ]

    weekends = [
      ~D[2019-04-05],
      ~D[2019-04-12],
      ~D[2019-04-19],
      ~D[2019-04-26],
      ~D[2019-05-03],
      ~D[2019-05-10],
      ~D[2019-05-17],
      ~D[2019-05-24],
      ~D[2019-05-31],
      ~D[2019-06-07],
      ~D[2019-06-14],
      ~D[2019-06-21],
      ~D[2019-06-28]
    ]

    assert Grouping.group(weekends, events) == [
             %{
               "2019-04-05" => nil,
               "2019-04-12" => [
                 %{first_name: "Jane", hours: 1.0, id: 29, last_name: "Smith"},
                 %{first_name: "Josh", hours: 2.0, id: 24, last_name: "Proud"}
               ],
               "2019-04-19" => [%{first_name: "Josh", hours: 25.0, id: 24, last_name: "Proud"}],
               "2019-04-26" => [%{first_name: "Josh", hours: 1.0, id: 24, last_name: "Proud"}],
               "2019-05-03" => nil,
               "2019-05-10" => [
                 %{first_name: "Houman", hours: 1.0, id: 29, last_name: "Kargaran"}
               ],
               "2019-05-17" => nil,
               "2019-05-24" => nil,
               "2019-05-31" => nil,
               "2019-06-07" => nil,
               "2019-06-14" => [
                 %{first_name: "Houman", hours: 1.0, id: 29, last_name: "Kargaran"}
               ],
               "2019-06-21" => nil,
               "2019-06-28" => nil
             }
           ]
  end
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment