module Crypto.RLWE.Challenges.Beacon where
import Data.Int
import Data.Time.Calendar (fromGregorian)
import Data.Time.Clock (UTCTime (..), secondsToDiffTime)
import Data.Time.Clock.POSIX (utcTimeToPOSIXSeconds)
import Data.Time.LocalTime (getCurrentTimeZone, timeZoneMinutes)
type BeaconEpoch = Int64
type BeaconOffset = Int32
bytesPerBeacon :: BeaconOffset
bytesPerBeacon = 64
beaconInterval :: BeaconEpoch
beaconInterval = 60
data BeaconAddr = BA !BeaconEpoch !BeaconOffset deriving (Eq, Show)
validBeaconAddr :: BeaconAddr -> Bool
validBeaconAddr (BA epoch offset) =
(epoch `mod` beaconInterval == 0) && offset >= 0 && offset < bytesPerBeacon
nextBeaconAddr :: BeaconAddr -> BeaconAddr
nextBeaconAddr (BA time byteOffset) =
if byteOffset == bytesPerBeacon1
then BA (time+beaconInterval) 0
else BA time (byteOffset+1)
gmtDateToSeconds :: Int -> Int -> Integer -> Int -> Int -> Int
gmtDateToSeconds month day year hour minute |
hour >= 0 && hour < 24 && minute >= 0 && minute < 60 =
round $ utcTimeToPOSIXSeconds $
UTCTime (fromGregorian year month day)
(secondsToDiffTime $ fromIntegral $ 3600*hour+60*minute)
gmtDateToSeconds _ _ _ _ _ = error "invalid date to gmtDateToSeconds"
localDateToSeconds :: Int -> Int -> Integer -> Int -> Int -> IO BeaconEpoch
localDateToSeconds month day year hour minute = do
let gmt = gmtDateToSeconds month day year hour minute
minuteOffset <- timeZoneMinutes <$> getCurrentTimeZone
return $ fromIntegral $ gmt (minuteOffset*60)
beaconFloor :: BeaconEpoch -> BeaconEpoch
beaconFloor e = e e `mod` beaconInterval