packages feed

SCalendar-1.0.0: test/SCalendarTest/Internal.hs

module SCalendarTest.Internal where


import Data.List (elem)
import Data.Maybe (isJust, fromMaybe)
import Data.Time (UTCTime(..), toGregorian, diffUTCTime )
import SCalendarTest.Helpers (getUTCdayNum)
import Time.SCalendar.Types ( Calendar(..)
                            , Reservation(..)
                            , TimePeriod
                            , getFrom
                            , getTo
                            , isIncluded
                            , powerOfTwo
                            , oneDay
                            , makeTimePeriod )
import Time.SCalendar.Zippers (goUp)
import SCalendarTest.Arbitrary (RandomZippers(..), CalendarReservations(..))
import Time.SCalendar.Internal ( goToNode
                               , leftMostTopNode
                               , rightMostTopNode
                               , topMostNodes
                               , getZipInterval
                               , commonParent   )


alwaysGreateOrEqualThanN :: Int -> Bool
alwaysGreateOrEqualThanN n = 2^ powerOfTwo n >= n

eqIntervalsIfIncludeEachOther :: TimePeriod -> TimePeriod -> Bool
eqIntervalsIfIncludeEachOther i j
  | isIncluded i j && isIncluded j i = i1 == j1 && i2 == j2
  | isIncluded i j = not $ isIncluded j i
  | isIncluded j i = not $ isIncluded i j
  | not (isIncluded i j) && not (isIncluded j i) && wellFormed = i1 < j2 || j1 < i2
  | otherwise = not wellFormed
  where
    (i1, i2) = (getFrom i, getTo i)
    (j1, j2) = (getFrom j, getTo j)
    wellFormed = i1 <= i2 && j1 <= j2

returnsTargetZipper :: Calendar -> TimePeriod -> Bool
returnsTargetZipper calendar interval =
  let maybeCalendar = fst <$> goToNode interval calendar
  in maybe (ifNothing calendar) checkTarget maybeCalendar
  where
    checkTarget (Unit unit _ _) = unit == interval
    checkTarget (Node interval' _ _ _ _) = interval' == interval
    -- ^ --
    ifNothing (Node interval' _ _ _ _) =
      not $ isIncluded interval interval' && ((getUTCdayNum . getFrom) interval) `mod` 2 == 0
    ifNothing _ = False

isLeftMostTopNode :: CalendarReservations -> Bool
isLeftMostTopNode (CalReservs _ []) = False
isLeftMostTopNode (CalReservs calendar (reserv:_)) = fromMaybe False $ do
  i2 <- getZipInterval <$> leftMostTopNode i1 calendar
  return $ getFrom i2 == getFrom i1 &&
           if getTo i2 == getTo i1
           then  (getFrom i1, getTo i1) == (getFrom i2, getTo i2)
           else getTo i2 < getTo i1
  where
    i1 = reservPeriod reserv

isRightMostTopNode :: CalendarReservations -> Bool
isRightMostTopNode (CalReservs _ []) = False
isRightMostTopNode (CalReservs calendar (reserv:_)) = fromMaybe False $ do
  i2 <- getZipInterval <$> rightMostTopNode i1 calendar
  return $ getTo i2 == getTo i1 &&
           if getFrom i2 == getFrom i1
           then (getFrom i1, getTo i1) == (getFrom i2, getTo i2)
           else getFrom i2 > getFrom i1
  where
    i1 = reservPeriod reserv

returnsCommonParent :: RandomZippers -> Bool
returnsCommonParent (RandomZippers zip1 zip2) = fromMaybe False $ do
  parent <- commonParent zip1 zip2
  let c1 = getZipInterval zip1
      c2 = getZipInterval zip2
      p= getZipInterval parent
  return $ getFrom p <= getFrom c1 &&
           getFrom p <= getFrom c2 &&
           getTo p >= getTo c1 &&
           getTo p >= getTo c2

leftMostAndRightMostInTopMost :: CalendarReservations -> Bool
leftMostAndRightMostInTopMost (CalReservs _ []) = False
leftMostAndRightMostInTopMost (CalReservs calendar (reserv:_)) = fromMaybe False $ do
  ltmInterval <- getZipInterval <$> leftMostTopNode interval calendar
  rtmInterval <- getZipInterval <$> rightMostTopNode interval calendar
  topMostIntervals <- (fmap . fmap) getZipInterval (topMostNodes interval calendar)
  return $ (ltmInterval `elem` topMostIntervals) && (rtmInterval `elem` topMostIntervals)
  where
    interval = reservPeriod reserv

outerMostNodesIncludeIntermediate :: CalendarReservations -> Bool
outerMostNodesIncludeIntermediate (CalReservs _ []) = False
outerMostNodesIncludeIntermediate (CalReservs calendar (reserv:_)) = fromMaybe False $ do
  from' <- (getFrom . getZipInterval) <$> leftMostTopNode interval calendar
  to' <- (getTo . getZipInterval) <$> rightMostTopNode interval calendar
  topMostIntervals <- (fmap . fmap) getZipInterval (topMostNodes interval calendar)
  -- ^ Each intermediate interval must be included in the leftmost and rightmost ones
  let numDays = round $ diffUTCTime to' from' / oneDay
      (UTCTime gregDay _) = from'
      (year, month, day) = toGregorian gregDay
  timePeriod <- makeTimePeriod year month day numDays
  return $ all (`isIncluded` timePeriod)  topMostIntervals || timePeriod `elem` topMostIntervals
  where
    interval = reservPeriod reserv

ifOnlyOneTopNodeItEqualsInterval :: CalendarReservations -> Bool
ifOnlyOneTopNodeItEqualsInterval (CalReservs _ []) = False
ifOnlyOneTopNodeItEqualsInterval (CalReservs calendar (reserv:_)) = fromMaybe False $ do
  topMostIntervals <- (fmap . fmap) getZipInterval (topMostNodes interval calendar)
  if length topMostIntervals == 1
  then return $ head topMostIntervals == interval
  else return True
  where
    interval = reservPeriod reserv

parentOfTopNodesNotIncluded :: CalendarReservations -> Bool
parentOfTopNodesNotIncluded (CalReservs _ []) = False
parentOfTopNodesNotIncluded (CalReservs calendar (reserv:_)) = fromMaybe False $ do
  from' <- (getFrom . getZipInterval) <$> leftMostTopNode interval calendar
  to' <- (getTo . getZipInterval) <$> rightMostTopNode interval calendar
  tmNodes <- topMostNodes interval calendar
  parentIntervals <- (fmap . fmap) getZipInterval
                                  (sequence $ filter isJust (goUp <$> tmNodes))
  let numDays = round $ diffUTCTime to' from' / oneDay
      (UTCTime gregDay _) = from'
      (year, month, day) = toGregorian gregDay
  timePeriod <- makeTimePeriod year month day numDays
  return $ all (`notIncluded` timePeriod) parentIntervals
  where
    notIncluded i1 i2 = not $ isIncluded i1 i2
    -- ^ --
    interval = reservPeriod reserv