Skip to content

Instantly share code, notes, and snippets.

@barsumek
Created April 7, 2017 19:31
Show Gist options
  • Save barsumek/0cf765b797c011c23f141b9c079cd267 to your computer and use it in GitHub Desktop.
Save barsumek/0cf765b797c011c23f141b9c079cd267 to your computer and use it in GitHub Desktop.
Task 2
import java.time.format.DateTimeFormatter
import java.time.{LocalDate, LocalTime}
import scala.annotation.tailrec
object Sessions {
private val DateTimeFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
private val MinSessions = 6
private case class SessionDateTime(date: LocalDate, time: LocalTime)
private case class SessionCountByDate(date: LocalDate, sessionCount: Int)
private def parseDate(datetime: String) = SessionDateTime(
LocalDate.parse(datetime, DateTimeFormat),
LocalTime.parse(datetime, DateTimeFormat)
)
private def toSessionTime(sessions: Seq[SessionDateTime]) = sessions.map(dateTime => dateTime.time)
private def toSessionCountByDate(groupedSessions: (LocalDate, Seq[SessionDateTime])) =
SessionCountByDate(groupedSessions._1, countDaySessions(toSessionTime(groupedSessions._2)))
// main method
def shouldAskUserOpinion(userSessions: Seq[String]): Boolean = {
@tailrec
def checkSessions(firstDay: SessionCountByDate, nextSessions: Seq[SessionCountByDate]): Boolean =
nextSessions match {
case s if s.size < 2 => false
case Seq(secondDay, thirdDay, _*) if meetsOpinionCondition(firstDay, secondDay, thirdDay) => true
case _ => checkSessions(nextSessions.head, nextSessions.tail)
}
import scala.collection.breakOut
val sessionsCountedByDate: Seq[SessionCountByDate] = userSessions
.map(parseDate)
.groupBy(d => d.date)
.map(toSessionCountByDate)(breakOut)
.sortBy(_.date.toEpochDay)
checkSessions(sessionsCountedByDate.head, sessionsCountedByDate.tail)
}
private implicit val sessionDate: (SessionCountByDate => LocalDate) = _.date
private implicit val sessionCount: (SessionCountByDate => Int) = _.sessionCount
private def meetsOpinionCondition(first: SessionCountByDate, second: SessionCountByDate, third: SessionCountByDate) =
areThreeDaysConsecutive(first, second, third) && daysHaveEnoughSessions(first, second, third)
private def areThreeDaysConsecutive(first: LocalDate, second: LocalDate, third: LocalDate) =
first.plusDays(1).isEqual(second) && first.plusDays(2).isEqual(third)
private def daysHaveEnoughSessions(first: Int, second: Int, third: Int) = first + second + third >= MinSessions
private def countDaySessions(sessions: Seq[LocalTime]): Int = {
@tailrec
def count(currTime: LocalTime, sessions: Int, nextSessions: Seq[LocalTime]): Int =
nextSessions match {
case s if s.isEmpty => sessions
case _ =>
val nextTime = nextSessions.head
if (currTime.plusMinutes(30).isBefore(nextTime)) count(nextTime, sessions + 1, nextSessions.tail)
else count(nextTime, sessions, nextSessions.tail)
}
count(sessions.head, 1, sessions.tail)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment