Created
May 26, 2018 16:05
-
-
Save KamilLelonek/7a5acf3d18f90c23c270e15978ee2b57 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule Task2 do | |
@doc """ | |
Problem: | |
We would like to check what users are actively using one of our web applications and, if so, ask for their opinion. | |
Each user enters the application and navigates between pages. | |
For each user, we log whenever he or she opens main page or any other page. | |
Whenever he or she open a page for the first time or after a break of at least 30 minutes, | |
we count it as a new session. We will ask the user for his or her opinion | |
only when for the last three days he or she used the application each day | |
and in total he or she has had six unique sessions. | |
Task: | |
Write a function that will receive the log, i.e. a sequence of timestamps in chronological order. | |
Each timestamp denotes single time the user has opened the website. | |
The function should return True if we should ask the user for his or her opinion and False otherwise. | |
Timestamps are strings in the format of 'YYY-MM-DD hh:mm:ss', using user's time zone. | |
You can assume that the last entry is with today's date. | |
""" | |
@max_age 3 * 24 * 60 * 60 | |
@min_duration 30 * 60 | |
@spec call(datetimes :: [String.t()]) :: boolean() | |
def call(datetimes) when is_list(datetimes) do | |
datetimes | |
|> Enum.map(&to_datetime/1) | |
|> reject_too_old() | |
|> count_unique() | |
|> maybe_count_sessions() | |
|> should_ask?() | |
end | |
defp to_datetime(string) do | |
with {:ok, datetime, _} <- DateTime.from_iso8601("#{string}Z"), do: datetime | |
end | |
defp reject_too_old(datetimes), | |
do: Enum.reject(datetimes, &too_old?(List.last(datetimes), &1)) | |
defp too_old?(today, datetime), do: DateTime.diff(today, datetime) > @max_age | |
defp count_unique(datetimes), | |
do: {datetimes, unique_days_count(datetimes)} | |
defp unique_days_count(datetimes) do | |
datetimes | |
|> Enum.uniq_by(&DateTime.to_date/1) | |
|> Enum.count() | |
end | |
defp maybe_count_sessions({_datetimes, unique_count}) when unique_count < 3, do: false | |
defp maybe_count_sessions({datetimes, _unique_count}) do | |
datetimes | |
|> Enum.chunk_every(2) | |
|> Enum.map(&session?/1) | |
|> Enum.count(& &1) | |
end | |
defp session?([_datetime]), do: true | |
defp session?([d1, d2]), do: DateTime.diff(d2, d1) > @min_duration | |
defp should_ask?(false), do: false | |
defp should_ask?(count) when count < 3, do: false | |
defp should_ask?(_count), do: true | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment