Created
April 7, 2017 19:31
-
-
Save barsumek/0cf765b797c011c23f141b9c079cd267 to your computer and use it in GitHub Desktop.
Task 2
This file contains 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
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